architecture-samples icon indicating copy to clipboard operation
architecture-samples copied to clipboard

single live event, notify all observers

Open mhdabbaghy opened this issue 4 years ago • 1 comments

Hi, thanks for the example but I have a problem in SingleLiveEvent class there is a log that says "Multiple observers registered but only one will be notified of changes." but what if we want to notify all observers? in my scenario, I observed live data in 2 places and I want to notify all of them and also I need to treat it as an event

mhdabbaghy avatar Aug 10 '21 10:08 mhdabbaghy

Solution: Event Wrapper + MutableLiveData<List<Event<T>>> or a Custom MultiEventLiveData You can do one of two things:

Option 1: Use a Custom Event Wrapper + Normal LiveData Create an Event wrapper:

open class Event<out T>(private val content: T) {

private var hasBeenHandled = false

fun getContentIfNotHandled(): T? =
    if (hasBeenHandled) null
    else {
        hasBeenHandled = true
        content
    }

fun peekContent(): T = content

} In your ViewModel:

private val _multiEvent = MutableLiveData<Event<String>>() val multiEvent: LiveData<Event<String>> = _multiEvent

fun triggerEvent() { _multiEvent.value = Event("Notify all!") } Then in your fragments/activities:

viewModel.multiEvent.observe(viewLifecycleOwner) { event -> event.getContentIfNotHandled()?.let { // Will run once per observer instance, but each must manage its own "handled" state doSomethingWith(it) } } This notifies all observers, but each observer handles the event only once per emission.

Option 2: Create MultiLiveEvent That Notifies All Observers Once If you still want a cleaner abstraction like SingleLiveEvent but for multiple observers, you can make a custom class:

class MultiLiveEvent<T> : MutableLiveData<T>() {

private val pending = mutableSetOf<Observer<in T>>()

override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
    pending.add(observer)

    super.observe(owner) { t ->
        if (pending.contains(observer)) {
            observer.onChanged(t)
            pending.remove(observer)
        }
    }
}

override fun setValue(value: T?) {
    pending.clear()
    super.setValue(value)
}

} This ensures all registered observers get the value once.

VaradGupta23 avatar Jul 18 '25 11:07 VaradGupta23