Kotlin中的Lazy和Lateinit属性

439 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,[点击查看活动详情]

Kotlin中的Lazy和Lateinit属性

Kotlin语言中提供了许多对于我们开发者来说很好的功能,我们可以使用这些特性快速的构建一个高质量的应用程序,在所有的这些特性中,lateinitlazy是很重要的初始化属性。你知道它俩在什么时候使用吗?

lateinit

我们有些时候变量的值在其声明的地方是需要要初始化的。比如,在我们开发中就会遇到一些UI组件在Activity或者是Fragment中的onCreate或者是oncCreateView中才会被初始化的,或者是在需要引用这个UI组件的地方才会被初始化。

class HomeFragment:Fragment(){
	private var sureButton:Button? = null
}

在Kotlin中的声明就必须被初始化,但是在Kotlin中又不允许像Java中那样,先声明,到之后才初始化。那么我们在初始化的时候就喜欢让这种变量可空,并且在声明的时候就将该变量置为null。但是我们在使用可空类型的时候,在后续的代码中使用该变量时,我们都必须使用空校验来检查。然后就会出现一连串烦人的问号,如果你刚出Java转向Kotlin开发,这样就会让你的代码看起来特别混乱。

fun initView(){
	sureButton?.let{
		....
	}
}

那么我们怎么在Kotlin中实现和Java那样先声明,再初始化呢?我们就可以使用lateinit修饰符就可以完全做到这一点。

class HomeFragment:Fragment(){
	private lateinit var sureButton:Button
}

使用lateinit修饰过后,kotlin将允许你先声明不给它复制。但是该变量必须是可变的var类型,这样Kotlin就会知道你稍后会对这个值进行赋值。通过lateinit修饰符,你可以为变量不适用Kotlin中的空校验。但是如果你忘记了在之后的代码中忘记对lateinit声明的变量进行初始化,就会抛出UninitializedPropertyAccessException的异常

什么时候使用lateinit
  • 如果变量是可变的并且可以在稍后阶段初始化。
  • 您确定要在使用变量之前对其进行初始化。
  • 使用 var关键字.

lazy

在软件工程中有一种常见的模式叫做推迟创建和初始化对象,知道真正需要使用的时候才会创建。这种模式被称为延迟初始化。因为在android中应用在启动期间创建大量对象就会导致启动事件变长。下面就是Java中的延迟初始化

class MyClass {
    private HeavyObject heavy;
    public HeavyObject getHeavy() {
        if (heavy == null) {
            heavy = new HeavyObject();
        }
        return heavy;
    }

这种写法当首次需要该值的时候会常见新实例,后续如果再次使用都是使用缓存的实例对象。但是在Kotlin原生语言中是支持延迟初始化的,可以使用by lazy来提供初始化块

class  MyClass  { 
    val  heavy  by  lazy  {  // 初始化块
        HeavyObject() 
    } 
}
何时使用by lazy
  • 除非你调用它,否则变量不会被初始化。
  • 初始化变量一次;然后在整个代码中使用相同的值。
  • 在属性的情况下使用,val即作为同一对象的只读属性将在整个程序中共享。