属性或对象的延时加载是我们相当常用的,一般我们都是使用 lateinit 和 by lazy 来实现。 他们两者都是延时初始化,那么在使用时那么他们两者有什么区别呢? lateinit 见名知意,延时初
属性或对象的延时加载是我们相当常用的,一般我们都是使用 lateinit 和 by lazy 来实现。 他们两者都是延时初始化,那么在使用时那么他们两者有什么区别呢? lateinit见名知意,延时初始化的标记。lateinit var可以让我们声明一个变量并且不用马上初始化,在我们需要的时候进行手动初始化即可。 如果我们不初始化会怎样?
会报错: 所以对应这一种情况我们会有一个是否初始化的判断
lateinit var的作用相对较简单,其实就是让编译期在检查时不要因为属性变量未被初始化而报错。(注意一定要记得初始化哦!) by lazyby lazy 委托延时处理,分为委托和延时 其实如果我们不想延时初始化,我们直接使用委托by也可以实现。
我们通过 by Delegates 的方式就可以指定委托对象,这里我用的 Delegates.obsevable 它的作用是修改 age 的值之后会有回调的处理。 运行的效果: 除了 Delegates.obsevable 它还有其他的用法。
其实用不用委托没什么区别,就是看是否需要属性变化的回调监听,否则我们直接用变量即可
如果我们想实现延时初始化的关键就是 lazy 关键字,所以,lazy是如何工作的呢? 让我们一起在Kotlin标准库参考中总结lazy()方法,如下所示:
简单地说,lazy创建一个实例,在第一次访问属性值时执行初始化,存储结果并返回存储的值。
由于我们使用的是 by lazy ,归根到底还是一种委托,只是它是一种特殊的委托,它的过程是这样的: 我们的属性 age 需要 by lazy 时,它生成一个该属性的附加属性:age?delegate。 在构造器中,将使用 lazy(()->T) 创建的 Lazy 实例对象赋值给 age?delegate。 当该属性被调用,即其getter方法被调用时返回 age?delegate.getVaule(),而 age?delegate.getVaule()方法的返回结果是对象 age?delegate 内部的 _value 属性值,在getVaule()第一次被调用时会将_value进行初始化并储存起来,往后都是直接将_value的值返回,从而实现属性值的唯一一次的初始化,并无法再次修改。所以它是只读的。 当我们调用这个 age 这个属性的时候才会初始化,它属于一种懒加载,既然是懒加载,就必然涉及到线程安全的问题,我们看看lazy是怎么解决的。
我们需要考虑的是线程安全和非线程安全
总结总的来说其实 lateinit 是延迟初始化, by lazy 是懒加载即初始化方式已确定,只是在使用的时候执行。 虽然两者都可以推迟属性初始化的时间,但是 lateinit var 只是让编译期忽略对属性未初始化的检查,后续在哪里以及何时初始化还需要开发者自己决定。而by lazy真正做到了声明的同时也指定了延迟初始化时的行为,在属性被第一次被使用的时候能自动初始化。 并且 lateinit 是可读写的,by lazy 是只读的。 那我们什么时候该使用 lateinit,什么时候使用 by lazy ? 其实大部分情况下都可以通用,只是 by lazy 一般用于非空只读属性,需要延迟加载情况,而 lateinit 一般用于非空可变属性,需要延迟加载情况。 |
2022-04-23
2022-01-26
2021-11-15
2021-08-02
2019-12-15