Skip to content

Instantly share code, notes, and snippets.

@cuub
Created September 17, 2019 16:01
Show Gist options
  • Save cuub/aff2a441506ccf89e82c5d006aa04789 to your computer and use it in GitHub Desktop.
Save cuub/aff2a441506ccf89e82c5d006aa04789 to your computer and use it in GitHub Desktop.
A lifecycle-aware observable that sends the event only once to all observers. Similar o SingleLiveEvent but supporting multiple observers.
class LiveDataShotOnce<T> : MutableLiveData<T>() {
private val observerWrapperMap = WeakHashMap<Observer<in T>, ObserverWrapper<in T>>()
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
val observerWrapper = ObserverWrapper(observer)
observerWrapperMap[observer] = observerWrapper
super.observe(owner, observerWrapper)
}
@MainThread
override fun observeForever(observer: Observer<in T>) {
observerWrapperMap[observer] = ObserverWrapper(observer)
super.observeForever(observer)
}
@MainThread
override fun removeObserver(observer: Observer<in T>) {
val wrapper: ObserverWrapper<in T>? = if (observer is ObserverWrapper) observer else observerWrapperMap[observer]
if (wrapper != null) {
observerWrapperMap -= wrapper.originalObserver
super.removeObserver(wrapper)
}
}
@MainThread
override fun setValue(value: T) {
observerWrapperMap.values.forEach(ObserverWrapper<in T>::setPending)
super.setValue(value)
}
private class ObserverWrapper<ObsW>(val originalObserver: Observer<ObsW>) : Observer<ObsW> {
private var pending = false
fun setPending() {
pending = true
}
override fun onChanged(t: ObsW) {
if (!pending) return
pending = false
originalObserver.onChanged(t)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment