kotlin 学习笔记一

Koltin中属性在声明的同时也要求要被初始化,否则会报错。例如以下代码:

  1. private var name0: String //报错

  2. private var name1: String = "xiaoming" //不报错

  3. private var name2: String? = null //不报错

我并不想声明一个类型可空的对象,而且我也没办法在对象一声明的时候就为它初始化,那么这时就需要用到Kotlin提供的延迟初始化
  Kotlin中有两种延迟初始化的方式。一种是lateinit var,一种是by lazy。 lateinit 只用于变量 var,而 lazy 只用于常量 val 

lateinit var

private lateinit var name: String

  lateinit var只能用来修饰类属性,不能用来修饰局部变量,并且只能用来修饰对象,不能用来修饰基本类型(因为基本类型的属性在类加载后的准备阶段都会被初始化为默认值)。.lateinit不能用在可空的属性上和java的基本类型上
  lateinit var的作用也比较简单,就是让编译期在检查时不要因为属性变量未被初始化而报错。
  Kotlin相信当开发者显式使用lateinit var 关键字的时候,他一定也会在后面某个合理的时机将该属性对象初始化的

 by lazy

  by lazy本身是一种属性委托。属性委托的关键字是by。by lazy 的写法如下:

  1. //用于属性延迟初始化

  2. val name: Int by lazy { 1 }

  3. //用于局部变量延迟初始化

  4. public fun foo() {

  5. val bar by lazy { "hello" }

  6. println(bar)

  7. }

  以下以name属性为代表来讲解by kazy的原理,局部变量的初始化也是一样的原理。
  by lazy要求属性声明为val,即不可变变量,在java中相当于被final修饰。
  这意味着该变量一旦初始化后就不允许再被修改值了(基本类型是值不能被修改,对象类型是引用不能被修改)。{}内的操作就是返回唯一一次初始化的结果。
  by lazy可以使用于类属性或者局部变量。

  写一段最简单的代码分析by lazy的实现:

  1. class TestCase {

  2. private val name: Int by lazy { 1 }

  3. fun printname() {

  4. println(name)

  5. }

  6. }

 lazy 应用于单例模式(if-null-then-init-else-return),而且当且仅当变量被第一次调用的时候,委托方法才会执行。lateinit 则用于只能生命周期流程中进行获取或者初始化的变量,比如 Android 的 onCreate()

lazy默认是线程安全的,你当然也可以关掉这个配置,只需要加个参数即可:

by lazy(LazyThreadSafetyMode.NONE)

如果你想要线程安全,使用 blockingLazy(): 它还是按照同样的方式工作,但保证了它的值只会在一个线程中计算,并且所有的线程都获取的同一个值。

class Preference<T>(val context: Context, val name: String, val default: T) : ReadWriteProperty<Any?, T> {

    val prefs by lazy { context.getSharedPreferences("default", Context.MODE_PRIVATE) }

    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return findPreference(name, default)
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putPreference(name, value)
    }

    private fun <U> findPreference(name: String, default: U): U = with(prefs) {
        val res: Any = when (default) {
            is Long -> getLong(name, default)
            is String -> getString(name, default)
            is Int -> getInt(name, default)
            is Boolean -> getBoolean(name, default)
            is Float -> getFloat(name, default)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }

        res as U
    }

    private fun <U> putPreference(name: String, value: U) = with(prefs.edit()) {
        when (value) {
            is Long -> putLong(name, value)
            is String -> putString(name, value)
            is Int -> putInt(name, value)
            is Boolean -> putBoolean(name, value)
            is Float -> putFloat(name, value)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }.apply()
    }
}

  

var aInt: Int by Preference(this, "aInt", 0)
    
    fun whatever(){
        println(aInt)//会从SharedPreference取这个数据
        aInt = 9 //会将这个数据写入SharedPreference
    }
发布了74 篇原创文章 · 获赞 36 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/kdsde/article/details/89676851