In certain case like Home Widget (AppWidgetProvider
), I don't have access to Activity
or Fragment
.
Usually, I use ProcessLifecycleOwner.get()
, or the following LifeCycleOwner
to observe 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; } }
In most situation, in the callback of LiveData
, I will try to remove LifeCycleOwner
from further observing LiveData
, by using liveData.removeObserver
.
However, there are situation where
- LiveData fails to trigger callback.
- Hence, I didn't remove LifeCycleOwner from LiveData in LiveData's callback.
In such situation, will it cause resource leakage? For instance, GC notice a long life LifeCycleOwner
is observing LiveData A
. Although LiveData
A is already out of scope, GC will not free-up LiveData A
, because a long living LifeCycleObserver
still observing it?
If so, how can I resolve this kind of leakage?
3 Answers
Answers 1
will it cause resource leakage?
Answer : I don't think so that this kind of scenario will make memory leak.
Why?
Because, as we can see that once LiveData
is out of scope for any LifecyclerOwner
, it removes reference if you set your LifecycleOwner
at DESTROYED state.
see observe()
method documentation;
Adds the given observer to the observers list within the lifespan of the given owner. The events are dispatched on the main thread. If
LiveData
already has data set, it will be delivered to the observer.The observer will only receive events if the owner is in STARTED or RESUMED state (active).
If the owner moves to the DESTROYED state, the observer will automatically be removed.
When data changes while the owner is not active, it will not receive any updates. If it becomes active again, it will receive the last available data automatically.
LiveData
keeps a strong reference to the observer and the owner as long as the givenLifecycleOwner
is not destroyed. When it is destroyed,LiveData
removes references to the observer & the owner.If the given owner is already in DESTROYED state,
LiveData
ignores the call.If the given owner, observer tuple is already in the list, the call is ignored. If the observer is already in the list with another owner,
LiveData
throws anIllegalArgumentException
.
TL;DR
So, according to above documentation, from line :
If the owner moves to the DESTROYED state, the observer will automatically be removed.
If the given owner is already in DESTROYED state, LiveData ignores the call.
it's clear that if your LifecycleOwner
has no scope (already in DESTROYED state), then LiveData
removes it's strong reference thus there's no chance of memory leak.
how can I resolve this kind of leakage? & get callback all the time:
Answer : You've already created your own LifecycleOwner
, so I'll suggest you to handle it yourself. make your LiveData
to observeForever()
& handle removal (removeObserver()
) yourself once your LifecycleOwner
reaches to DESTROYED state.
this will not cause memory leak. because it's stated in document: (This means that the given observer will receive all events and will never be automatically removed)
Adds the given observer to the observers list. This call is similar to
observe(LifecycleOwner, Observer)
with a LifecycleOwner, which is always active. This means that the given observer will receive all events and will never be automatically removed. You should manually callremoveObserver(Observer)
to stop observing thisLiveData
. WhileLiveData
has one of such observers, it will be considered as active.If the observer was already added with an owner to this
LiveData
,LiveData
throws anIllegalArgumentException
.
This will help you receive callback all the time, you just need to handle how you can remove callback once done.
Hope it helps !
Answers 2
In above example, if don’t clear that reference explicitly (as we would usually do in activity/fragments onStop()); there will be a risk of memory leak.
Answers 3
To track every memory leak in your app and find out what's causing it you can try out this library github.com/square/leakcanary
its really useful tool and easy to use.
0 comments:
Post a Comment