Issue
Using Android X
and the Android Architecture Components
, namely the following...
- Navigation
- Lifecycle
- ViewModel
... has made Android development much easier for better and more stable apps.
When using a ViewModel
exposing LiveData
s for a Fragment
, there are currently two LifecycleOwners that can be used to oberve:
- the
Fragment
itself or - the
Fragment
's propertymViewLifecycleOwner
.
Up until now, I have always and exclusively use the Fragment
itself for any and all LiveData
exposed by ViewModel
s.
As I like to live on the edge by frequently upgrading to the latest alphas & betas, I have recently upgraded to:
- navigation ktx version
2.2.0-rc01
; - activity ktx version
1.1.0-rc01
; - fragment ktx version
1.2.0-rc01
; - lifecycle ktx version
2.2.0-rc01
;
OK luckily, at this date (1st nov 2019), there were all available as release candidates.
This had the consequence to warn me in old java code:
How come there is actually two LifecycleOwners ?
Should I also follow this warning when setting the lifecycle owner of the Fragment's databound layout (using the Databinding
library) ?
Then what's the use for the Fragment itself as a LifecycleOwener
?
Solution
There are two different lifecycles because the Fragment itself lives longer than the Fragment's view.
There are a number of events that can cause the Fragment's view to be destroyed, but currently keep the Fragment itself alive:
- Putting the Fragment on the back stack (i.e., when you
navigate()
to another Fragment) - Calling
detach()
on a Fragment - Calling
setMaxLifecycle(Lifecycle.State.CREATED)
on a Fragment
In these cases, the Fragment's view is destroyed, moving the Fragment view lifecycle to DESTROYED
. However, the lifecycle of Fragment itself is not destroyed - it generally stays as CREATED
. This means that the Fragment can go through multiple cycles of onCreateView()
-> onViewCreated()
-> onDestroyView()
while only going through onCreate()
once.
Where this becomes a problem is when it comes to how LiveData
works. When you observe
a LiveData
, LiveData
automatically unregisters the observer when the lifecycle reaches DESTROYED
. But if you use the Fragment's lifecycle to observe
in onCreateView()
, etc., that registered observer will still exist after onDestroyView()
, despite the view being destroyed. This means that the second time your Fragment goes through onCreateView()
, you'll actually create a second active Observer, with both running simultaneously. Then three Observers the next time and on and on.
By using the view LifecycleOwner in onCreateView()
/onViewCreated()
, you ensure that you'll only have one active Observer running at a time and that Observers tied to previous view instances are correctly destroyed along with the view. Therefore, yes, you should always use getViewLifecycleOwner()
as the LifecycleOwner when in onCreateView()
or onViewCreated()
, including when using Data Binding.
Of course, if you're registering an Observer in onCreate()
, then the view LifecycleOwner does not exist yet (it is created right before onCreateView()
) and you don't have the multiple registration problem, which is why the Lint check specifically does not apply to any registrations done at onCreate()
time. In those cases, using the Fragment's lifecycle itself is absolutely correct.
As per the Fragments: Past, Present, and Future talk, one future improvements for Fragments is going to be combining the two lifecycles together, always destroying the Fragment whenever the Fragment's view is destroyed. This is not yet available in any shipped version of Fragments, alpha or otherwise.
Answered By - ianhanniballake
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.