如果LifeCycleOwner长寿地观察LiveData,是否会导致资源泄漏?

时间:2018-10-03 06:56:47

标签: android

在某些情况下,例如Home Widget(AppWidgetProvider),我无权访问ActivityFragment

通常,我使用ProcessLifecycleOwner.get()或以下LifeCycleOwner来观察LiveData

public enum ForeverStartLifecycleOwner implements LifecycleOwner {
    INSTANCE;

    private final LifecycleRegistry mLifecycleRegistry;

    ForeverStartLifecycleOwner() {
        mLifecycleRegistry = new LifecycleRegistry(this);
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

在大多数情况下,在LiveData的回调中,我将尝试通过使用LifeCycleOwner从进一步观察LiveData的过程中删除liveData.removeObserver

但是,在某些情况下

  1. LiveData无法触发回调。
  2. 因此,我没有在LiveData的回调中从LiveData中删除LifeCycleOwner。

在这种情况下,会导致资源泄漏吗?例如,GC注意到LifeCycleOwner使用寿命很长LiveData A。尽管LiveData A已经超出范围,但是GC仍无法释放LiveData A,因为寿命长的LifeCycleObserver仍在观察它?

如果是这样,我该如何解决这种泄漏?

2 个答案:

答案 0 :(得分:-1)

  

会导致资源泄漏吗?

答案:我不认为这种情况会导致内存泄漏。

为什么?

因为我们可以看到,一旦LiveData超出了任何LifecyclerOwner的范围,如果将LifecycleOwner设置为 DESTROYED 状态,它将删除引用

请参见observe()方法文档;


  

obesrve()

     

将给定的观察者添加到以下对象的观察者列表中:   给定的所有者。事件在主线程上调度。如果   LiveData已经设置了数据,它将被发送给观察者。

     

仅当所有者位于 STARTED 或   已恢复状态(有效)。

     

如果所有者移至 DESTROYED 状态,观察者将   自动删除。

     

当所有者不活动时更改数据时,将不会收到   任何更新。如果再次激活,它将收到最后一个   自动提供数据。

     

LiveData强烈引用观察者和所有者作为   只要给定的LifecycleOwner不被破坏。几时   LiveData被销毁后,将删除对观察者和所有者的引用。

     

如果给定的所有者已经处于 DESTROYED 状态,则LiveData将忽略   打电话。

     

如果给定的所有者观察者元组已经在列表中,则调用为   忽略了。如果观察者已经在列表中,并且拥有另一个所有者,   LiveData引发 IllegalArgumentException


TL; DR

因此,根据上述文档,从第

行:
  • 如果所有者变为DESTROYED状态,则观察者将被自动删除。

  • 如果给定的所有者已经处于DESTROYED状态,LiveData将忽略 通话。

很明显,如果您的LifecycleOwner没有范围(已经处于 DESTROYED 状态),那么LiveData会删除它的强引用,因此就不会出现内存泄漏的可能性。


  

我该如何解决这种泄漏?并始终获取回调:

答案::您已经创建了自己的LifecycleOwner,所以建议您自己处理。使您的LiveData达到 DESTROYED 状态后,将您的observeForever()移至removeObserver()并自行处理LifecycleOwner

这不会导致内存泄漏。因为它在文档中说明: (这意味着给定的观察者将收到所有事件,并且永远不会被自动删除)

  

observeForever()

     

将给定的观察者添加到观察者列表中。 此呼叫类似于   observe(LifecycleOwner, Observer)和一个LifecycleOwner,即   始终处于活动状态 这意味着给定的观察者将收到所有   事件,并且永远不会被自动删除 。您应该手动   呼叫removeObserver(Observer)以停止观察此LiveData。而   LiveData有这样的观察者之一,它将被视为活动

     

如果观察者已经与所有者添加到此LiveData中,   LiveData抛出IllegalArgumentException

这将帮助您始终接收回调,只需要处理完成后如何删除回调的操作即可。

希望有帮助!

答案 1 :(得分:-2)

在上面的示例中,如果未明确清除该引用(就像我们通常在活动/片段onStop()中所做的那样);会有内存泄漏的风险。