kotlin入门(中)

11.数据类【data class 类名()】

  • 11.1 数据类型的样式 data class Forecast(val date: Date, val temperature: Float, val details: String)
  • 11.2 复制一个数据类对象(val 是不可变的,相当于java中final) val f1 = Forecast(Date(), 27.5f, “Shiny day”) val f2 = f1.copy(temperature = 30f)
  • 11.3 映射对象到变量中
    val f1 = Forecast(Date(), 27.5f, “Shiny day”) val (date, temperature, details) = f1 相当于:
    val date = f1.component1()
    val temperature = f1.component2()
    val details = f1.component3()
    并且映射对象到变量,可以这样用
    privete val map = mapOf(String,String)(
                    Pair("01","---1111111"), <br>
                    Pair("02","---2222222"), <br>
                       Pair("03","--333333333"), <br>
                       Pair("04","---4444444") <br>
      ) <br>
              for ((key, value) in map) { <br>
                      Log.d("map", "key:$key, value:$value") <br>
                  }    )</li>
    


12.companion objects 在类中定义静态常量、方法、属性
      我们需要一个类里面有一些静态的属性、常量或者函数,我们可以使用companion objecvt。
      这个对象被这个类的所有对象所共享,就像Java中的静态属性或者方法。

13.kotlin函数的返回值

一切kotlin函数都会返回一个值。如果没有指定,它就默认返回一个Unit类

14.遍历list集合,并对集合中的每个数据进行操作,然后返回一个新的对象的集合

private fun convertForecastListToDomain(list: List):
List {
/**
这一条语句,我们就可以循环这个集合并且返回一个转换后的新的List。
Kotlin在List中提供了很多不错的函数操作符,
它们可以在这个List的每个item中应用这个操作并且任何方式转换它们

           */
           return  list.map { convertForecastItemToDomain(it) }           }

      private fun convertForecastItemToDomain(forecast: Forecast):

ModelForecast {
return ModelForecast(covertData(forecast.dt),forecast.weather[0].description,
forecast.temp.max.toInt(),
forecast.temp.min.toInt()) }

15.当一个文件中出现了类名相同的2个类,我们可以为其中一个指定别名,这样我们就不需要写完整的包名了:

//第一个被引入的类名 import weather.demo.com.hellokotlin03.bean.Forecast
//第二个被引入的类名 import weather.demo.com.hellokotlin03.domain.Forecast
as ModelForecast
16.with函数

with是一个非常有用的函数,它包含在Kotlin的标准库中。 它接收一个对象和一个扩展函数作为它的参数,然后使这个对象扩展这个函数。
这表示所有我们在括号中编写的代码都是作为对象(第一个参数)的一个扩展函数,
我们可以就像作为this一样使用所有它的public方法和属性。 当我们针对同一个对象做很多操作的时候这个非常有利于简化代码。
17.Lambdas : Lambda表达式是一种很简单的方法,去定义一个匿名函数【with(){}函数就是使用到这个了 ::inline fun with(t: T, body: T.() -> Unit) { t.body() }】

使用Lambdas简化setOnClickListener()           与java进行对比:

      Java:           view.setOnClickListener(new OnClickListener(){
          @Override
          public void onClick(View v) {
              Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show();
          }           })

      kotlin:             view.setOnClickListener(object : OnClickListener {
          override fun onClick(v: View) {
              toast("Click")
          }           }

      Lambdas对kotlin进行简化:             view.setOnClickListener { toast("Click") }


      简化过程:           (1)fun setOnClickListener(listener: (View) -> Unit)
      (2)一个lambda表达式通过参数的形式被定义在箭头的左边(被圆括号包围),然后在箭头的右边返回结果值。在这个例子中,我们接收一个View,然后返回一个Unit(没有东西)
          【我们必须使用大括号包围,然后在箭头的左边指定参数,在箭头的右边返回函数执行的结果】
          view.setOnClickListener({ view -> toast("Click")})          (3)如果左边的参数没有使用到,我们甚至可以省略左边的参数
          view.setOnClickListener({ toast("Click") })             (4)如果这个函数的最后一个参数是一个函数,我们可以把这个函数移动到圆括号外面:
          view.setOnClickListener() { toast("Click") }            (5)如果这个函数只有一个参数,我们可以省略这个圆括号:
          view.setOnClickListener { toast("Click") }          ============================================================
        使用Lambdas简化监听的回调与参数的传入
  • 17.1 接收监听【这个itemClick函数接收一个forecast参数然后不返回任何东西】
    public class ForecastListAdapter(val weekForecast: ForecastList,val itemClick: (Forecast) -> Unit)

  • 17.2 传递监听【构造中需要的参数放在()中,监听的参数由于是最后一个参数,所以能放在()后面】

            val adapter = ForecastListAdapter(weekForecast) { forecast -> toast(forecast.date) }
    
  • 17.3 如果这个函数只接收一个参数,那我们可以使用it引用,而不用去指定左边的参数
    val adapter = ForecastListAdapter(weekForecast) { toast(it.date) }

  • 17.4 调用这个监听【this,就是】
    itemView.setOnClickListener { itemClick( new Forecast() ) }

18.内联函数【像ladbdsa后面{}中的函数就是内联函数】

内联函数与普通的函数有点不同。一个内联函数会在编译的时候被替换掉,而不是真正的方法调用。
这在一些情况下可以减少内存分配和运行时开销。举个例子,如果我们有一个函数,只接收一个函数作为它的参数。
如果是一个普通的函数,内部会创建一个含有那个函数的对象。
另一方面,内联函数会把我们调用这个函数的地方替换掉,所以它不需要为此生成一个内部的对象。
举个例子: (1)自定义一个函数: inline fun supportsLollipop(code: () -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
code()
} } (2)调用这个函数 supportsLollipop {
window.setStatusBarColor(Color.BLACK) }

19.私有化构造器

class C private constructor(a: Int) { … }

20.函数的返回值可以省略: 在Kotlin中,我们不需要去指定一个函数的返回值类型,它可以让编译器推断出来。

应用场景:我们可以省略返回值类型的典型情景是当我们要给一个函数或者一个属性赋值的时候。而不需要去写代码块去实现。 data class
ForecastList(val city: String, val country: String,val
dailyForecast:List) { operator fun get(position: Int) =
dailyForecast[position] //没有返回值类型,不去写代码块,直接用=返回 fun size() : Int
= dailyForecast.size }

21.使用Kotlin Android Extensions【当前仅仅包括了view的绑定。这个插件自动创建了很多的属性来让我们直接访问XML中的view。这种方式不需要你在开始使用之前明确地从布局中去找到这些views。】
【Kotlin Android Extensions插件帮助我们减少了很多模版代码,并且简化了我们访问view的方式】
步骤:

(1)在项目的gradle中添加依赖库 dependencies {
classpath “org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version” }
(2)在Activities或者Fragments中使用,需要手动的添加
import kotlinx.android.synthetic.[xml的名字].* (3)在一个自定义view或者一个adapter中使用,需要手动添加,【在xml名字后面,需要添加一个View.*】
import kotlinx.android.synthetic.[xml的名字].view.*

22.委托属性【使用了by这个关键字来指定一个委托对象。】
我们可能需要一个属性具有一些相同的行为,使用lazy或者observable可以被很有趣地实现重用。
而不是一次又一次地去声明那些相同的代码,Kotlin提供了一个委托属性到一个类的方法。这就是我们知道的委托属性。

      属性委托的结构如下:          class Delegate<T> : ReadWriteProperty<Any?, T> {
          fun getValue(thisRef: Any?, property: KProperty<*>): T {
              return ...
          }

          fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
              ...
          }           }       这个T是委托属性的类型。getValue函数接收一个类的引用和一个属性的元数据。setValue函数又接收了一个被设置的值。如果这个属性是不可修改(val),就会只有一个getValue函数。

  下面展示属性委托是怎么设置的:         class Example {             var p: String by Delegate()         }

23.标准委托

(1)Lazy:【lazy操作符是线程安全的】它包含一个lambda,当第一次执行getValue的时候这个lambda会被调用,所以这个属性可以被延迟初始化。
之后的调用都只会返回同一个值。这是非常有趣的特性, 当我们在它们第一次真正调用之前不是必须需要它们的时候。
我们可以节省内存,在这些属性真正需要前不进行初始化。
如果你不担心多线程问题或者想提高更多的性能,你也可以使用lazy(LazyThreadSafeMode.NONE){ … }
(2)Observable
这个委托会帮我们监测我们希望观察的属性的变化。当被观察属性的set方法被调用的时候,它就会自动执行我们指定的lambda表达式。
所以一旦该属性被赋了新的值,我们就会接收到被委托的属性、旧值和新值。

      例子展示了:一些我们需要关心的ViewMode,每次值被修改了,就会保存它们到数据库。             class ViewModel(val

db: MyDatabase) {
var myProperty by Delegates.observable(“”) {
d, old, new ->
db.saveChanges(this, new)
} }
(3)Vetoable 这是一个特殊的observable,它让你决定是否这个值需要被保存。它可以被用于在真正保存之前进行一些条件判断。
例子展示了:这个委托只允许在新的值是正数的时候执行保存。在lambda中,最后一行表示返回值。你不需要使用return关键字(实质上不能被编译)。
var positiveNumber = Delegates.vetoable(0) {
d, old, new ->
new >= 0 } (4)Not Null 它会含有一个可null的变量并会在我们设置这个属性的时候分配一个真实的值。如果这个值在被获取之前没有被分配,它就会抛出一个异常。
class App : Application() {
companion object {
var instance: App by Delegates.notNull()
}

          override fun onCreate() {
              super.onCreate()
              instance = this
          }           }       (5)从Map中映射值             import kotlin.properties.getValue           import kotlin.properties.setValue
      另外一种属性委托方式就是,属性的值会从一个map中获取value,属性的名字对应这个map中的key。
      这个委托可以让我们做一些很强大的事情,因为我们可以很简单地从一个动态地map中创建一个对象实例。            如果我们import

kotlin.properties.getValue,我们可以从构造函数映射到val属性来得到一个不可修改的map。
如果我们想去修改map和属性,我们也可以import
kotlin.properties.setValue。类需要一个MutableMap作为构造函数的参数。
想象我们从一个Json中加载了一个配置类,然后分配它们的key和value到一个map中。

      我们可以仅仅通过传入一个map的构造函数来创建一个实例:
          import kotlin.properties.getValue

          class Configuration(map: Map<String, Any?>) {
              val width: Int by map
              val height: Int by map
              val dp: Int by map
              val deviceName: String by map
              }           作为一个参考,这里我展示下对于这个类怎么去创建一个必须要的map:
          conf = Configuration(mapOf(
              "width" to 1080,
              "height" to 720,
              "dp" to 240,
              "deviceName" to "mydevice"
          ))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值