single live event, notify all observers
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
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.