5

I want to use LiveData in a Fragment to observe the change of some data. Now let's suppose:

  1. Both the Fragment A and Fragment B have their own containers layout in Activity, which means we will call FragmentTransaction#add() separately for them and their onPause() or onResume() will not be called during adding(UI change) because of no FragmentTransaction#replace() action.
  2. B's container is larger than A's, which means if B is added, users cannot see A.
  3. In A there is a LiveData observer named as O, it will observe the change of some data, and update UI according to it. The key is: we want to play some animation for the change, instead of just calling properties setter (like TextView#setText()) naively. For example, maybe the animation is the one played after we called RecyclerView.Adapter#notifyItemInserted()

After adding B, A is considered as invisible to users. However, both the lifecycle of Fragment A or of its View by calling getViewLifecycleOwner() is still on STARTED and RESUMED state. As a result, the animation will play after the data changes observed by O but users cannot see it from the beginning.

How can we solve this problem? Any ideas or answers are appreciated. Thanks in advance.

Scrobot
  • 1,911
  • 3
  • 19
  • 36
ywwynm
  • 11,573
  • 7
  • 37
  • 53

1 Answers1

2

If you are adding B (which consumes the space supposedly alloted for A), it is better to also remove fragment A. You get multiple benefits for this:

1) You solve your problem. (Thats if youre using viewLifeCycleOwner in observing your LiveData) 2) You decrease memory consumption of your app, since the Fragment A's view will be torn down.

This is

which means we will call FragmentTransaction#add() separately

is also not a problem. Note that you can chain FragmentTransactions such as:

supportFragmentManager.beginTransaction()
    .replace(view1.id, fragmentB)
    .remove(fragmentA)
    .commit()
Archie G. Quiñones
  • 11,638
  • 18
  • 65
  • 107
  • 5
    Note that `hide()` literally just sets the alpha on the Fragment. It has no effect on the Lifecycle of the Fragment. – ianhanniballake Apr 24 '19 at 04:08
  • 1
    `FragmentTransaction#show()/hide()` will not influence the lifecycle of either `Fragment` or its view – ywwynm Apr 24 '19 at 04:28
  • @ianhanniballake ohh... then just use `.remove()` then i guess? – Archie G. Quiñones Apr 24 '19 at 04:43
  • by the way hi @ianhanniballake!! :D :D – Archie G. Quiñones Apr 24 '19 at 04:44
  • @ArchieG.Quiñones We cannot use `FragmentTransaction#remove()` in this case, because A should not be removed just for this reason and it has many other things to do. – ywwynm Apr 24 '19 at 05:36
  • @ywwynm how about `.detach()` then? – Archie G. Quiñones Apr 24 '19 at 05:38
  • 1
    Also, it seems that the `it has many other things to do` isn't view related so I don't think you need fragment for that (unless im wrong). Have you considered moving that `it has many other things to do` to a `ViewModel` perhaps or to the `Activity` itself or where ever you want to place it. – Archie G. Quiñones Apr 24 '19 at 05:44
  • @ArchieG.Quiñones You're still talking about removing A but I don't want to do that. By saying "many other things", they are still possibly UI-related because not all UI change should be with animation. I just don't want the lifecycle of A remaining `STARTED` or `RESUMED` in that situation and this is all about lifecycle, not the fragment itself. – ywwynm Apr 24 '19 at 10:47
  • 1
    The arguement remains. You can seperate that logic outside of the fragment scope. Then youre not restricted about your fragment removal, etc. You cannot change the fact that LiveData always listens to change as long as the observer is active but you can control how you structure your code. – Archie G. Quiñones Apr 24 '19 at 17:26