作者:Antonio Leiva 時間:Dec 27, 2016 原文鏈接:https://antonioleiva.com/custom-views-android-kotlin/ 在我們閱讀有關class文章時,你可能記得通常情況下僅用一個構造函數。這對於要創建定製視圖就是一個問題。 Andro ...
時間:Dec 27, 2016
原文鏈接:https://antonioleiva.com/custom-views-android-kotlin/
在我們閱讀有關class文章時,你可能記得通常情況下僅用一個構造函數。這對於要創建定製視圖就是一個問題。
Android框架希望有多個構造函數對應不同的創建視圖位置和創建視圖方法(通過代碼、使用XML,設置主題,等等),這樣我們就不能忽略這種情況。
為此,Kotlin團隊提供了同一個類中有多個構造函數的能力,就如同這裡所說的。
相容Java是Kotlin的基礎要求,所以無論你遇到什麼情況,就應該想到必定有方法實現你的需要。
在Kotlin中創建定製視圖
即使你已經有創建定製視圖的經驗和一些Kotlin知識,也可能第一次在Kotlin中創建定製視圖,你會發現有點複雜。
在Kotlin中實現幾個構造函數是最為複雜的工作之一,準確地說,這是比較罕見用法。
但是,不用擔心,一旦你接觸過一次,其餘的都是非常相似的。
註:儘管本文能有效的幫助你理解如何使用在Kotlin類中用多個構造函數,但是,Kirill Rakhman在評論提及的方法是更好的方法。在結尾閱讀。
創建繼承View的類
為了這樣,就如我們早前見到的那樣創建一個類。例如它繼承View,但不說明任何構造函數:
1 class KotlinView : View { 2 }
由於這段代碼邀請調用父類的構造函數,所以這段地面不能編譯。
例如,如果你僅僅是在Kotlin代碼中擴展你的視圖,你可能用我們已經見到的唯一的構造函數形式:
1 class KotlinView(context: Context?) : View(context) { 2 }
但是要小心,由於如果決定在這個視圖加XML,它將失敗。
說明:你見到在Context右邊的問號嗎?在Kotlin中,如果我們要變數或參數是null,我們就必須用問號明確地指明它。之後編譯器將要求我們在使用該變數前檢查它不能為null。在下一篇文章閱讀這點。
實現多構造函數
構造函數用保留字constructor,它可以是同類的另一個構造函數(用this)或一個父類(用super)。
這是你定義Android視圖的構造函數:
1 class KotlinView : View { 2 3 constructor(context: Context?) : this(context, null) 4 constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0) 5 6 constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { 7 ... 8 } 9 10 }
更簡單實現方法
在評論中,Kirill提及(非常感謝!)另一種方法更簡單、更易閱讀。它是基於為構造函數的自變數分配預設值,但是需要一點點調整。
問題是在你用自變數預設值創建構造函數(或任何函數)時,在Kotlinzhong產生的位元組碼僅僅允許用那些預設值。如果在Java中,你用構造函數,你可以強制說明所有自變數的值。
這是因為Java沒有這樣的語言特性。在Java中,你要依據你的需要通過產生函數重載解決它。
在Kotlin中,你可以用@JvmOverloads註釋得到自動產生的代碼。
代碼像這樣:
1 class KotlinView @JvmOverloads constructor( 2 context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 3 ) : View(context, attrs, defStyleAttr)
結論
一旦你瞭解它,產生包含有多個構造函數的定製的視圖也不複雜了,用@JvmOverloads註釋則更容易。
這對於任何需要多個構造函數的類是都非常有用。但總的來說,如你能賦值參數的預設值(從而避免重載),通常就不需要多個構造函數。
如果你要瞭解更多這方面知識編寫實際的APP,我建議你閱讀我書《Android開發者的Kotlin》。
在Kotlin中創建定製視圖