閱讀:Null檢查機制及lateinit與by lazy(委托機制)的應用
https://blog.csdn.net/Shenpibaipao/article/details/76974461
lateinit 和 lazy 是 Kotlin 中的兩種不同的延遲初始化的實作
lateinit 隻用于變量 var,而 lazy 隻用于常量 val
lazy 應用于單例模式(if-null-then-init-else-return),而且當且僅當變量被第一次調用的時候,委托方法才會執行。
lazy()
是接受一個 lambda 并傳回一個
Lazy <T>
執行個體的函數,傳回的執行個體可以作為實作延遲屬性的委托: 第一次調用
get()
會執行已傳遞給
lazy()
的 lambda 表達式并記錄結果, 後續調用
get()
隻是傳回記錄的結果。
val lazyValue: String by lazy {
println("computed!")
"Hello"
}
fun main(args: Array<String>) {
println(lazyValue)
println(lazyValue)
}
列印結果
computed!
Hello
Hello
比如這樣的常見操作,隻擷取,不指派,并且多次使用的對象
private val mUserMannager: UserMannager by lazy {
UserMannager.getInstance()
}
再比如acitivity中控件初始化的操作,一般傳統的進入界面就初始化所有的控件,而使用懶加載,隻有用到時才會對控件初始化
//kotlin 封裝:
fun <V : View> Activity.bindView(id: Int): Lazy<V> = lazy {
viewFinder(id) as V
}
//acitivity中擴充調用
private val Activity.viewFinder: Activity.(Int) -> View?
get() = { findViewById(it) }
//在activity中的使用姿勢
val mTextView by bindView<TextView>(R.id.text_view)
mTextView.text="執行到我時,才會進行控件初始化"
或
val mLayoutContext:ViewGroup by lazy{
findViewById(R.id.mLayoutContent) as ViewGroup
}
lateinit(延遲初始化屬性)
一般地,屬性聲明為非空類型必須在構造函數中初始化(我們知道,kotlin中預設是空安全的,任何屬性的聲明都必須有初始化值,如果支援可空”?”,才能把屬性聲明為null)。然而這樣經常不友善,例如:屬性可以通過依賴注入來初始化,或者單元測試的setup方法中初始化,這種情況下,你不能在構造函數内提供一個非空初始器,但你仍然想在類體中引用該屬性時避免空檢查。為處理這種情況,我們可以使用lateinit
val nameA:String //報紅線 提示如下
Property must be initialized or be abstract
lateinit var name:String //lateinit可以避免這種情況
該修飾隻能用于類體中(不是在主構造函數中)聲明的var屬性,注意是var(可變屬性)并且僅當該屬性沒有自定義getter或setter時,該屬性必須是非空類型,并且不能是原生類型。
在初始化前通路一個lateinit屬性會抛出一個特定異常,該異常明确辨別該屬性被通路及它沒有初始化的事實。