代码之家  ›  专栏  ›  技术社区  ›  ssuukk

Kotlin代表更有趣

  •  5
  • ssuukk  · 技术社区  · 7 年前

    如果你知道谷歌的实验性安卓架构组件,你可能知道 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 回复  |  直到 7 年前
        1
  •  3
  •   hotkey    7 年前

    你可以 access the delegate object 并获得 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 .

        2
  •  3
  •   ssuukk    7 年前

    多亏了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"

    这个类支持使用LiveData和Android数据绑定。

        3
  •  2
  •   holi-java    7 年前

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

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

    然后可以在类中使用实时数据,例如:

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

    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;