在某些情况下,例如Home Widget(AppWidgetProvider
),我无权访问Activity
或Fragment
。
通常,我使用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
。
但是,在某些情况下
在这种情况下,会导致资源泄漏吗?例如,GC注意到LifeCycleOwner
使用寿命很长LiveData A
。尽管LiveData
A已经超出范围,但是GC仍无法释放LiveData A
,因为寿命长的LifeCycleObserver
仍在观察它?
如果是这样,我该如何解决这种泄漏?
答案 0 :(得分:-1)
会导致资源泄漏吗?
答案:我不认为这种情况会导致内存泄漏。
为什么?
因为我们可以看到,一旦LiveData
超出了任何LifecyclerOwner
的范围,如果将LifecycleOwner
设置为 DESTROYED 状态,它将删除引用
请参见observe()
方法文档;
将给定的观察者添加到以下对象的观察者列表中: 给定的所有者。事件在主线程上调度。如果
LiveData
已经设置了数据,它将被发送给观察者。仅当所有者位于 STARTED 或 已恢复状态(有效)。
如果所有者移至 DESTROYED 状态,观察者将 自动删除。
当所有者不活动时更改数据时,将不会收到 任何更新。如果再次激活,它将收到最后一个 自动提供数据。
LiveData
强烈引用观察者和所有者作为 只要给定的LifecycleOwner
不被破坏。几时LiveData
被销毁后,将删除对观察者和所有者的引用。如果给定的所有者已经处于 DESTROYED 状态,则
LiveData
将忽略 打电话。如果给定的所有者观察者元组已经在列表中,则调用为 忽略了。如果观察者已经在列表中,并且拥有另一个所有者,
LiveData
引发IllegalArgumentException
。
因此,根据上述文档,从第
行:如果所有者变为DESTROYED状态,则观察者将被自动删除。
如果给定的所有者已经处于DESTROYED状态,LiveData将忽略 通话。
很明显,如果您的LifecycleOwner
没有范围(已经处于 DESTROYED 状态),那么LiveData
会删除它的强引用,因此就不会出现内存泄漏的可能性。
我该如何解决这种泄漏?并始终获取回调:
答案::您已经创建了自己的LifecycleOwner
,所以建议您自己处理。使您的LiveData
达到 DESTROYED 状态后,将您的observeForever()
移至removeObserver()
并自行处理(LifecycleOwner
)。
这不会导致内存泄漏。因为它在文档中说明: (这意味着给定的观察者将收到所有事件,并且永远不会被自动删除)
将给定的观察者添加到观察者列表中。 此呼叫类似于
observe(LifecycleOwner, Observer)
和一个LifecycleOwner,即 始终处于活动状态。 这意味着给定的观察者将收到所有 事件,并且永远不会被自动删除 。您应该手动 呼叫removeObserver(Observer)
以停止观察此LiveData
。而LiveData
有这样的观察者之一,它将被视为活动。如果观察者已经与所有者添加到此
LiveData
中,LiveData
抛出IllegalArgumentException
。
这将帮助您始终接收回调,只需要处理完成后如何删除回调的操作即可。
希望有帮助!
答案 1 :(得分:-2)
在上面的示例中,如果未明确清除该引用(就像我们通常在活动/片段onStop()中所做的那样);会有内存泄漏的风险。