Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More fun with Kotlin delegates

If you know Google's experimental Android Architecture Components, you probably know MutableLiveData. Trying to make it a bit more fun to use I came with:

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)
        }
    }
}

And then I can:

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

But alas - that makes data which is needed i.e. to register Observer inaccessible:

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

Any idea if I can get it somehow?

like image 318
ssuukk Avatar asked Mar 08 '23 17:03

ssuukk


1 Answers

You can access the delegate object of the property and get the MutableLiveData<T> from it:

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

Then the usage is:

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

To reference a member property, use this::name or someInstance::name.

This solution requires you to add the Kotlin reflection API, kotlin-reflect, as a dependency to your project. Also, due to the type erasure, the .delegateAs<KotlinLiveData<String>> call is not type-safe: it can only check that the delegate is KotlinLiveData<*> but not that its type argument is String.

like image 111
hotkey Avatar answered Mar 11 '23 07:03

hotkey