Android Kotlin筆記 — Delegate(二)
在上一篇中,示範了如何在Activity 使用 delegate 來簡化程式碼,在本篇中將同樣的應用在Fragment中。
在開始之前,先來說一個很重要的概念:不要重載Fragment的建構子!
這樣的做法很方便,而且在初期開發時不會發現有什麼問題,但是當QA在測試的時候,就會開始收到下面的錯誤訊息:
android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment
make sure class name exists, is public, and has an empty constructor that is public他會告訴你應該要有一個empty constructor,那這是為什麼呢?如果追一下Android open source code 就會發現在正常的情況下,FragmentManager 會使用你指定的instance,所以即使不是empty constructor也是沒問題的!(有興趣的可以看一下這邊 BackStackRecord 的 doAddOp())
那是哪邊出了問題呢?詳細情形可以看看這篇:http://blog.csdn.net/xplee0576/article/details/43057633
現在拉回正題,正確的傳遞參數方式還是要藉由intent,但是每個Fragment都要做這些很煩的 bundle.setString(), bundle.getString(), blabla… 現在就用Delegate 來幫我們節省開發時間吧!
delegate -ReadWriteProperty
kotlin 提供了這個 interface 讓我們可以委派變數的get(), set()行為。最簡單的使用方法是建立一個 ReadWriteProperty 的匿名類別
現在我們想要做一件事,在Fragment的任何地方使用 variable時,讓這個ReadWriteProperity 幫我呼叫背後的 arguments.getString(),而在建立Fragment時,使用fragment.variable = “whatEver”,幫我呼叫 arguments.setString(“whatEver”),下方是完成之後的樣子
好了!現在可以很簡單的使用variable,不需要getString或setString了。下一步,讓他可以被覆用。
Extension Function
跟上一篇一樣,這裡再一次的使用了這個特性,Fragment多一個 function 回傳這個 delegate,讓其他Fragment也可以覆用。
更加彈性
Fragment的每一個 argument 的 key應該要不一樣,所以再做一點小修正:
接受泛型
寫了這麼多卻只能使用 String 當然不會滿意,所以現在讓他也接受 Boolean, Int, Long吧!
另一種選擇
剛剛暫時忽略了ReadWriteProperty<in R, T> 中的 R,他是做什麼用呢?來看看文件中寫什麼:@param R the type of object which owns the delegated property.。也就是說他代表了可以使用這個 delegate 的 class 型別,所以現在我們可以利用這個來限制只有 Fragment 才可以使用,並且使用 thisRef 來拿 Fragment 的實體。
又因為現在可以拿到 Fragment 的實體了,所以不需要使用Extension Function 才能拿到 arguments了,再用實體類別取代匿名類別:
總結
在這裡示範了 delegate 來讓平常很囉唆的語法使用起來簡單很多,他可以使用在很多不同的場景,SharedPreference, SQLite…。如果你還不熟 delegate,現在就動手自己做一個吧!
