Mackovich
Mackovich

Reputation: 3593

LifecycleOwner: difference between Fragment (self) and Fragment#viewLifecycle

Using Android X and the Android Architecture Components, namely the following...

... has made Android development much easier for better and more stable apps.

When using a ViewModel exposing LiveDatas for a Fragment, there are currently two LifecycleOwners that can be used to oberve:

  1. the Fragment itself or
  2. the Fragment's property mViewLifecycleOwner.

Up until now, I have always and exclusively use the Fragment itself for any and all LiveData exposed by ViewModels.

As I like to live on the edge by frequently upgrading to the latest alphas & betas, I have recently upgraded to:

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:

enter image description here

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?

Upvotes: 15

Views: 8426

Answers (1)

ianhanniballake
ianhanniballake

Reputation: 200020

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:

  1. Putting the Fragment on the back stack (i.e., when you navigate() to another Fragment)
  2. Calling detach() on a Fragment
  3. 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.

Upvotes: 59

Related Questions