上下文在生命周期感知的 LiveEvent 中为空。

huangapple go评论75阅读模式
英文:

Context is null in Lifecycle aware LiveEvent

问题

以下是您要翻译的内容:

我的项目目前正在使用以下的SingleLiveEvent实现。

class SingleLiveEvent<T>(
    private val allowMultipleObservers: Boolean = false
) : MutableLiveData<T>() {

    private val mPending = AtomicBoolean(false)
    private val observers = mutableSetOf<Observer<in T>>()

    @MainThread
    override fun observe(
        owner: LifecycleOwner,
        observer: Observer<in T>
    ) {

        if (!allowMultipleObservers && hasActiveObservers()) {
            Timber.tag(TAG)
                .w("Multiple observers registered but only one will be notified of changes.")
        } else {
            observers.add(observer)
        }

        // Observe the internal MutableLiveData
        super.observe(owner, Observer { t ->
            if (mPending.compareAndSet(true, false)) {
                observers.forEach { observer ->
                    observer.onChanged(t)
                }
            }
        })
    }
...

当我们在onResumeonCreateView内部执行以下操作时:

SingleLiveEvent.observe(viewLifecycleOwner) {
   requireContext()
}

有时我们会收到一个崩溃报告,指出Context为空。然而,requireContext()不应该总是向我们提供一个有效的Context值吗?因为它是附加到viewLifecycleOwner的。

英文:

My project is currently using the following SingleLiveEvent implementation.

class SingleLiveEvent&lt;T&gt;(
    private val allowMultipleObservers: Boolean = false
) : MutableLiveData&lt;T&gt;() {

    private val mPending = AtomicBoolean(false)
    private val observers = mutableSetOf&lt;Observer&lt;in T&gt;&gt;()

    @MainThread
    override fun observe(
        owner: LifecycleOwner,
        observer: Observer&lt;in T&gt;
    ) {

        if (!allowMultipleObservers &amp;&amp; hasActiveObservers()) {
            Timber.tag(TAG)
                .w(&quot;Multiple observers registered but only one will be notified of changes.&quot;)
        } else {
            observers.add(observer)
        }

        // Observe the internal MutableLiveData
        super.observe(owner, Observer { t -&gt;
            if (mPending.compareAndSet(true, false)) {
                observers.forEach { observer -&gt;
                    observer.onChanged(t)
                }
            }
        })
    }
...

When we do this inside of onResume or onCreateView

SingleLiveEvent.observe(viewLifecycleOwner) {
   requireContext()
}

We sometimes receive a crash saying that the Context is null. However, shouldn't requireContext() always give us a valid Context value since it's attached to the viewLifecycleOwner?

答案1

得分: 1

你的实现有缺陷 - 只要观察者以非活动状态注册(或现有观察者变为非活动状态),那么你传递给 super.observe 的观察者封装将会失败,因为你强制调用 onChanged 来处理所有观察者,而不考虑它们的实际状态。

你应该用 hasObservers() 替代 hasActiveObservers()。但就个人而言,我会考虑使用实现了 MediatorLiveData 的解决方案,因为这个实现并没有正确处理进入已销毁状态的观察者,导致它们会永远保留在你的 observers 列表中。

英文:

Your implementation is flawed - it's possible to register multiple observers as long as they attach in inactive state (or existing observers became inactive), then observer wrapper you passed to super.observe will fail because you're forcing a call to onChanged for all observers disregarding their actual state.

You should replace hasActiveObservers() with hasObservers(). But personally I'd look into solution implementing MediatorLiveData since this implementation doesn't properly handle observers that enter destroyed state, leaving them in your observers list forever.

答案2

得分: 0

requireContext()除了与getContext()进行空指针检查比较外,并没有特别的功能。

来自谷歌的答复:

我们应该如何修复这个问题?
首先,我们应该修复潜在的错误。

  • 查找所有可能在某个时刻分离片段的地方
  • 修改代码,如下面的示例

在Java中:

Context context = getContext();
if (context == null) {
    // 处理空上下文场景
} else {
    // 带有上下文的旧代码
}

来源:https://medium.com/@shafran/fragment-getcontext-vs-requirecontext-ffc9157d6bbe

英文:

requireContext() does nothing special except for null-check comparing to getContext().

Answer from Google:

How should we fix that?
Firstly we should fix potentials bugs.

  • Find all places where fragment can be detached at some point of time
  • Change code like in the sample below

In Java:

Context context = getContext();
if (context == null) {
    // Handle null context scenario
} else {
    // Old code with context
}

Source: https://medium.com/@shafran/fragment-getcontext-vs-requirecontext-ffc9157d6bbe

huangapple
  • 本文由 发表于 2020年9月1日 00:40:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63674793.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定