Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@hadilq
Last active February 8, 2021 08:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hadilq/f095120348a6a14251a02aca329f1845 to your computer and use it in GitHub Desktop.
Save hadilq/f095120348a6a14251a02aca329f1845 to your computer and use it in GitHub Desktop.
class LiveEvent<T> : MediatorLiveData<T>() {
private val observers = ConcurrentHashMap<LifecycleOwner, MutableSet<ObserverWrapper<T>>>()
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<T>) {
val wrapper = ObserverWrapper(observer)
val set = observers[owner]
set?.apply {
add(wrapper)
} ?: run {
val newSet = Collections.newSetFromMap(ConcurrentHashMap<ObserverWrapper<T>, Boolean>())
newSet.add(wrapper)
observers[owner] = newSet
}
super.observe(owner, wrapper)
}
override fun removeObservers(owner: LifecycleOwner) {
observers.remove(owner)
super.removeObservers(owner)
}
override fun removeObserver(observer: Observer<T>) {
observers.forEach {
if (it.value.remove(observer)) {
if (it.value.isEmpty()) {
observers.remove(it.key)
}
return@forEach
}
}
super.removeObserver(observer)
}
@MainThread
override fun setValue(t: T?) {
observers.forEach { it.value.forEach { wrapper -> wrapper.newValue() } }
super.setValue(t)
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
fun call() {
value = null
}
private class ObserverWrapper<T>(private val observer: Observer<T>) : Observer<T> {
private val pending = AtomicBoolean(false)
override fun onChanged(t: T?) {
if (pending.compareAndSet(true, false)) {
observer.onChanged(t)
}
}
fun newValue() {
pending.set(true)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment