2017-08-04 67 views
3

我正在試用來自Google的Architecture Components。具體來說,我想實現一個ViewModelProvider.Factory創建一個視圖模型是需要構造函數的參數,就像這樣:kotlin中的Android ViewModelProviderFactory

class MyFactory(val handler: Handler) : ViewModelProvider.Factory { 
    override fun <T : ViewModel?> create(modelClass: Class<T>?): T { 
     return MyViewModel(handler) as T 
    } 
} 

我的視圖模型是這樣的:

class MyViewModel(val handler: Handler) : ViewModel() 

任何人知道如何避免到底討厭的投:

return MyViewModel(handler) as T 
+1

你正在做一個危險的工作......客戶端代碼期望一個'T擴展ViewModel',但你給一個'MyViewModel'。當客戶端代碼使用特定類型的'T'時,你總是得到'ClassCastException',例如:'val model:T = factory.create(T :: class.java)' –

+0

這就是爲什麼我想知道替代方法:) – Entreco

+1

你可以使用反射來實例化ViewModel或使用第三個IoC容器來創建ViewModel。 –

回答

4

你可以寫:

class MyFactory(val handler: Handler) : ViewModelProvider.Factory { 
    override fun <T : ViewModel> create(modelClass: Class<T>): T { 
     return modelClass.getConstructor(Handler::class.java).newInstance(handler) 
    } 
} 

這將適用於接受Handler作爲構造函數參數的任何類,如果該類沒有正確的構造函數,將拋出NoSuchMethodException

+0

由於這應該被稱爲非常罕見,反射的代價似乎是合理的。本來希望有一些時髦的Kotlin好東西,但是這樣做會。謝謝! – Entreco

+1

不幸的是,在這種情況下,像泛化的泛型類型的Kotlin好吃的東西不可用。由於類型刪除,您只能強制投射或使用反射。此外,默認工廠已經使用反射來調用空的公共構造函數,所以成本大致相同。 – BladeCoder