Kotlin代表更有趣

如果您了解Google的实验性Android架构组件,您可能会知道MutableLiveData 。 试图使它更有趣使用我来与:

 class KotlinLiveData<T>(val default: T) { val data = MutableLiveData<T>() operator fun getValue(thisRef: Any?, property: KProperty<*>):T { return data.value ?: default } operator fun setValue(thisRef: Any?, property: KProperty<*>, value:T) { if (Looper.myLooper() == Looper.getMainLooper()) { data.value = value } else { data.postValue(value) } } } 

然后我可以:

 var name : String by KotlinLiveData("not given") name = "Chrzęszczybrzęczykiewicz" 

但是,唉 – 这使得需要注册的数据Observer无法访问:

 name.data.observe(this, nameObserver) // won't work :( 

任何想法,如果我能得到它?

您可以访问该属性的委托对象 ,并从中获取MutableLiveData<T>

 inline fun <reified R> KProperty<*>.delegateAs<R>(): R? { isAccessible = true return getDelegate() as? R } 

那么用法是:

 ::name.delegateAs<KotlinLiveData<String>>?.data?.observe(this, nameObserver) 

要引用成员属性,请使用this::namesomeInstance::name

此解决方案要求您将Kotlin反射API kotlin-reflect作为依赖项添加到您的项目中。 另外,由于类型擦除, .delegateAs<KotlinLiveData<String>>调用不是类型安全的:它只能检查委托是否是KotlinLiveData<*>而不是它的类型参数是String

您可以实现的最简单的方法是使委托人到一个字段,例如:

 @JvmField val dataOfName = KotlinLiveData("not given") var name : String by dataOfName 

那么你可以在课堂上使用实时数据,例如:

 dataOfName.data.observe(this, nameObserver) name = "Chrzęszczybrzęczykiewicz" 

或者你可以写一些语法suglar,例如:

 var name : String by live("not given").observe(this, nameObserver) 

请注意,您也可以使nameObserver变得nameObserver ,例如:

 val observers by lazy{mutableListOf<Observer>()} var name : String by live("not given").observe(this){data-> observers.forEach{it.dataChanged(data)} } 

那么你可以做如下的事情:

 observers+= nameObserver; name = "Chrzęszczybrzęczykiewicz" observers-= nameObserver; 

感谢热键的解决方案,这里有一些更好的代码:

 class KotlinLiveData<T>(val default: T, val liveData : MutableLiveData<T>? = null) { val data = liveData ?: MutableLiveData<T>() operator fun getValue(thisRef: Any?, property: KProperty<*>):T { return data.value ?: default } operator fun setValue(thisRef: Any?, property: KProperty<*>, value:T) { if (Looper.myLooper() == Looper.getMainLooper()) { data.value = value } else { data.postValue(value) } } } inline fun <reified R> KMutableProperty0<*>.getLiveData(): MutableLiveData<R> { isAccessible = true return (getDelegate() as KotlinLiveData<R>).data } inline fun <reified R> KMutableProperty0<*>.observe(owner: LifecycleOwner, obs : Observer<R>) { isAccessible = true (getDelegate() as KotlinLiveData<R>).data.observe(owner,obs) } 

现在我能:

someViewModel::name.observe(myActivity, Observer<String>{...})

someViewModel.name = "Kowalski, Leon"

按预期工作

这个类可以使用LiveData与Android数据绑定开箱即用。