Kotlin的屬性委託:無上下文狀況下Android的賦值(KAD 15)

 

做者:Antonio Leivahtml

時間:Mar 9, 2017android

原文連接:https://antonioleiva.com/property-delegation-kotlin/緩存

 

 

如咱們在前面文章中讀到的,屬性須要默認值,不能聲明屬性,而不給它們賦值。安全

 

 

因爲你要存儲視圖到屬性中,這就產生一個問題了。在對象建立期間,這賦值代碼將被執行,而此時你不能訪問這個內容。app

 

 

那你有能作什麼?框架

 

 

屬性委託:委託屬性值到另外一個對象

 

 

 

屬性委託將使用另外一個對象,這個對象可以調用getset(若是使用了var)返回結果。ide

 

目前,咱們還不能控制許多對象的建立,如Android框架,在許多狀況下,這委託將挽救咱們的生命。函數

 

我將向你展現三個例子,我認爲它們在Android中很是有用。學習

 

設置視圖到屬性

 

對於這個例子,咱們用委託有兩個選項,且禁止用null(若是你可以避免它,有些事情不建議使用)。ui

 

這是我最喜歡的,由於它迫使你對於不可變的、不太安全的屬性使用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) }

 

textViewget被第一次調用以前,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應用程序,我建議你獲取這本免費指南,學習怎樣建立你的第一個項目,或直接獲取,學習怎樣從頭開始建立一個完整的應用程序。

相關文章
相關標籤/搜索