Android LiveData: Handle UI Event With Event Wrapper (SingleLiveEvent Replacement)

Aug 19, 2019

Why not to use LiveData to handle UI event? Because LiveData will trigger again upon configuation change / screen rotation. We want to handle UI event such as click once only.

The above problem could be solved using SingleLiveEvent.

Alternatively, you can use Event wrapper.

open class Event<out T>(private val value: T) {    private val pending = AtomicBoolean(true)    fun getIfPending(): T? {        return if (pending.compareAndSet(true, false)) {            value        }        else {            null        }    }    fun peek(): T = value    fun isPending(): Boolean = pending.get()}

NOTE: Based on Event by JoseAlcerreca

NOTE: Solution for multiple observers (I didn't try this)

Usage

val selectItemEvent = MutableLiveData<Event<Int>>()
// trigger ui event on item selectedselectItemEvent.value = Event(10)
selectItemEvent.observe(lifecycleOwner, Observer { event ->    val position = event.getIfPending()    if (position != null) {        // do something    }})

To reduce boilerplate code, you can use an EventObserver.

class EventObserver<T>(private val observe: (T) -> Unit) : Observer<Event<T>> {    override fun onChanged(event: Event<T>?) {        event?.getIfPending()?.let { value ->            observe(value)        }    }}

NOTE: Based on EventObserver by JoseAlcerreca

selectItemEvent.observe(lifecycleOwner, EventObserver { position ->    // do something})

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.