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::name
或someInstance::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数据绑定开箱即用。