哪个SingleLiveData可以处理屏幕旋转和观察之前发出的事件

问题描述 投票:0回答:1

在我的应用程序中,我需要一个LiveData,它发出一次。

我找到了一个不错的solution,但有几个问题:

  • 它不处理在调用LiveData.observe之前发出的事件。
  • 它不处理在屏幕旋转时(在片段的onDestroyViewonCreateView之间)发出的事件。

是否有一个可以处理所有列出的案例的实现?

android android-livedata
1个回答
0
投票

我基于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
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.