時間:Mar 9, 2017
原文鏈接:https://antonioleiva.com/property-delegation-kotlin/
如我們在前面文章中讀到的,屬性需要默認值,不能聲明屬性,而不給它們賦值。
由於你要存儲視圖到屬性中,這就產生一個問題了。在對象創建期間,這賦值代碼將被執行,而此時你不能訪問這個內容。
那你有能做什么?
屬性委托:委托屬性值到另一個對象
屬性委托將使用另一個對象,這個對象能夠調用get和set(如果使用了var)返回結果。
目前,我們還不能控制許多對象的創建,如Android框架,在許多情況下,這委托將挽救我們的生命。
我將向你展示三個例子,我認為它們在Android中非常有用。
設置視圖到屬性
對於這個例子,我們用委托有兩個選項,且禁止用null(如果你能夠避免它,有些事情不建議使用)。
這是我最喜歡的,因為它迫使你對於不可變的、不太安全的屬性使用var。
用保留字lateinit,說明屬性不能為空,但是我們仍然沒有final價值:
1 lateinit var textView:TextView
在onCreate,我們能夠賦值給final值:
1 setContentView(R.layout.activity_main) 2 textView = findView(R.id.welcomeMessage) 3 toast(textView.text)
盡管它與委托notNull做相同的操作、被歸入第一喜歡,但這不是真正的委托。
第二個選擇則更加優雅。它由Lazy委托組成,直至屬性第一次被調用,相關代碼是不會執行:
1 val textView by lazy { findView(R.id.welcomeMessage) }
在textView的get被第一次調用之前,findView是不能運行的。由於你不能錯誤的修改其值所以它更安全,並且它不會強制我們在setContentView之后記得設置它。
此刻,我們做:
1 toast(textView.text)
這行代碼將在lazy形式下被執行。
如你所見,委托的方式用by保留字表示。
我們來看另一個例子。
通知適配器變更
在適配器中,我們有items屬性,每次自動啟動adapter時更新。
1 var items: List by Delegates.observable(emptyList()) { 2 _, _, _ -> notifyDataSetChanged() 3 }
它簡單地設置初始值,然后在每次更改后調用定義的函數。
在這種情況下,我只是調用notifyDataSetChanged,但是,如你所見,函數收到的新舊兩個值,所以在技術上你可以檢查變化是什么,只更新其區別。
如果你對這個例子有興趣,我在另一篇文章更廣泛的描述它。
聲明Lazy方法的Dagger圖
這是我發現的非常有用的另一個情形。
返回到lazy,你能夠在屬性聲明期間,用它聲明應用的component:
1 val component: AppComponent by lazy { 2 DaggerAppComponent 3 .builder() 4 .appModule(AppModule(this)) 5 .build() 6 }
這個方法,你不需要用lateinit,屬性則為不可變的。
如果在Activity中,用subcomponents,你能夠做相同的事:
1 class HomeActivity : AppCompatActivity(), HomePresenter.View { 2 val component by lazy { app.component.plus(HomeModule(this)) } 3 ... 4 }
新Kotlin 1.1版本:局部委托屬性
我們已經見到怎樣用委托是給我們類屬性的額外能力。而例如lazy,對變量也真的有幫助嗎?Kotlin是缺乏這一特性的。
現在,用局部委托屬性,我們做:
1 fun testLocalDelegation() { 2 val database by lazy { createDatabase() } 3 val cache by lazy { createMemoryCache() } 4 5 if (mustUseDatabase()) { 6 database.use { ... } 7 } else { 8 cache.use { ... } 9 } 10 }
盡管不使用lazy委托,這個例子能夠解決,但它還是有助於理解這些概念。
我們有幾個可能會或不會被使用的“笨重”對象。通過用lazy,我們能夠推遲它們的實例化,直到我們確信要使用它們。
在首次使用時,花括號內的代碼被執行,且被緩存起來,以備以后再使用。
結論
屬性委托將幫助你屬性更強大,更簡化,且代碼可重用。
這里我們僅僅看到Kotlin庫的標准屬性,而你能夠創建你自己的屬性。
例如在這本書中,我有實現從SharedPreference存儲和取回數據。
如果你要學習更多這些內容,足夠流暢創建自己的Android應用程序,我建議你獲取這本免費指南,學習怎樣創建你的第一個項目,或直接獲取這本書,學習怎樣從頭開始創建一個完整的應用程序。