前言
Kotlin是一種在Java虛擬機(jī)上運(yùn)行的靜態(tài)類型編程語(yǔ)言,被稱之為Android世界的Swift,在GoogleI/O2017中,Google宣布Kotlin成為Android官方開(kāi)發(fā)語(yǔ)言

代理屬性
Kotlin中的代理屬性又被稱為屬性委托,屬性的操作就是set/get函數(shù)的調(diào)用,委托屬性會(huì)用自己的setValue/getValue去大理源屬性的實(shí)現(xiàn),委托類需要根據(jù)屬性的可變類型,實(shí)現(xiàn)對(duì)應(yīng)的setValue/getValue方法
屬性委托的語(yǔ)法:
val/var <屬性名>:屬性類型 by <表達(dá)式>
標(biāo)準(zhǔn)委托
Kotlin所提供的一些用于代理屬性的工廠方法
延遲屬性
使用lazy實(shí)現(xiàn)延遲屬性的委托,只在第一次首次訪問(wèn)的時(shí)候會(huì)計(jì)算
Kotlin中的lateinit、lazy關(guān)鍵字
可觀察屬性
每當(dāng)我們給屬性賦值的時(shí)候,就會(huì)在賦值后調(diào)用表達(dá)式中代碼塊,用于監(jiān)聽(tīng)屬性內(nèi)容的變更
var value:String by Delegates.observable("initValue"){
pro,old,new ->
Log.e("mike","----$pro----$old----$new")
}
value = "aaa"
value = "aaa"
value = "bbb"
//打印結(jié)果
----var com.mike.loginmvvm.login.ui.LoginActivity.value: kotlin.String----initValue----aaa
----var com.mike.loginmvvm.login.ui.LoginActivity.value: kotlin.String----aaa----aaa
----var com.mike.loginmvvm.login.ui.LoginActivity.value: kotlin.String----aaa----bbb
非空屬性代理
var data:String by Delegates.notNull()
Log.e("mike","----$data----")
//打印結(jié)果
Caused by: java.lang.IllegalStateException: Property data should be initialized before get.
查看它的源碼發(fā)現(xiàn),如果數(shù)據(jù)為空的時(shí)候會(huì)拋出異常
public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value ?: throw IllegalStateException("Property ${property.name} should be initialized before get.")
}
那么它和lateinit很相似,都是可以繞過(guò)編譯器檢查,都是初始化前直接使用會(huì)有異常拋出,就使用而言notNull可以用于基本數(shù)據(jù)類型,但lateinit只能用于引用數(shù)據(jù)類型
lateinit會(huì)生成這樣的代碼,這樣也能看出之所以lateinit不支持基本數(shù)據(jù)類型,也是因?yàn)榛緮?shù)據(jù)類型在java中存在默認(rèn)值的,所以不存在稍后初始化這種情況
lateinit var data:String
//java代碼
public String data;
public void get(){
if (data == null){
Intrinsics.throwUninitializedPropertyAccessException("data");
}
return data;
}
看下相同情況下的Delegates.notNull(),會(huì)產(chǎn)生一個(gè)包裝類的對(duì)象將數(shù)據(jù)進(jìn)行包裝
var value by Delegates.notNull<String>()
//會(huì)生成這樣的偽代碼
public NotNullVar value$delegate = new NotNullVar()
public String getValue(){
return value$delegate.getValue();
}
所以當(dāng)我們?cè)谶x擇Delegates.notNull()和lateinit的時(shí)候,如果是引用類型的需要延遲初始化的情況下推薦使用lateinit,開(kāi)銷相對(duì)較小,如果是基本數(shù)據(jù)類型就使用Delegates.notNull()
屬性值攔截
Delegates.observable可以查看數(shù)據(jù)的情況,在數(shù)據(jù)變化過(guò)后進(jìn)行回調(diào),vetoable則可以在數(shù)據(jù)提交之前進(jìn)行回調(diào),從而決定是否需要此次變更,當(dāng)返回false時(shí)表示丟棄此次變更
var version: Version by Delegates.vetoable(Version(0)) { pro, old, new ->
return@vetoable new.code > old.code
}
歡迎關(guān)注Mike的簡(jiǎn)書(shū)
Android知識(shí)整理