在我的应用程序中,我需要一个LiveData
,它发出一次。
我找到了一个不错的solution,但有几个问题:
onDestroyView
和onCreateView
之间)发出的事件。是否有一个可以处理所有列出的案例的实现?
我基于this article创建了自己的解决方案。它可以处理有问题的所有案例。
您可以在on github中找到带有注释的内容。
import androidx.annotation.MainThread
import androidx.collection.ArraySet
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.Observer
class EventLiveData<T>() : MediatorLiveData<T>() {
private val observers = ArraySet<ObserverWrapper<in T>>()
private var needToHandleLastResult = false
private val previouslyOwnersHashcodes = mutableSetOf<Int>()
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
val ownerHashcode = owner.hashCode()
val ownerAlreadyObserving = previouslyOwnersHashcodes.contains(ownerHashcode)
val needToHandleResult = needToHandleLastResult && !ownerAlreadyObserving
val wrapper = ObserverWrapper(observer, needToHandleResult)
previouslyOwnersHashcodes.add(ownerHashcode)
needToHandleLastResult = false
observers.add(wrapper)
super.observe(owner, wrapper)
}
@MainThread
override fun removeObserver(observer: Observer<in T>) {
if (observers.remove(observer)) {
super.removeObserver(observer)
return
}
val iterator = observers.iterator()
while (iterator.hasNext()) {
val wrapper = iterator.next()
if (wrapper.observer == observer) {
iterator.remove()
super.removeObserver(wrapper)
break
}
}
}
override fun onActive() {
needToHandleLastResult = false
super.onActive()
}
@MainThread
override fun setValue(t: T?) {
if (!hasActiveObservers()) {
needToHandleLastResult = true
}
observers.forEach { it.newValue() }
super.setValue(t)
}
private class ObserverWrapper<T>(
val observer: Observer<T>,
hasUnprocessedEvent: Boolean
) : Observer<T> {
private var pending = hasUnprocessedEvent
override fun onChanged(t: T?) {
if (pending) {
pending = false
observer.onChanged(t)
}
}
fun newValue() {
pending = true
}
}
}