与Kotlin代表一起享受更多乐趣

时间:2017-06-30 11:03:40

标签: delegates kotlin android-lifecycle android-databinding

如果您了解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"

但是唉 - 这需要data,即注册Observer无法访问:

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

知道我是否能以某种方式得到它?

3 个答案:

答案 0 :(得分:1)

您可以实现的最简单方法是将委托者设置为字段,例如:

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

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

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

OR 您可以编写一些语法,例如:

var name : String by live("not given").observe(this, 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;

答案 1 :(得分:1)

您可以access the delegate object获取该属性并从中获取Collections.sort(list);

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

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

答案 2 :(得分:0)

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

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"

按预期工作

此类允许使用带有Android数据绑定的LiveData。