1

I'm using navigation graph to navigate between fragments and I noticed that my viewModel is cleared (onCleared) only when I press the back button, but not when I navigating to another fragment using this code:

val action = MyFragmentDirections.actionMyFragmentToParentFragment()
        val navController =  findNavController()
        navController.navigate(action)

In the logs I see that the fragment onDestroyView() is called but the viewModel's onCleared() is not called.

What am I'm missing?

Sharas
  • 1,985
  • 3
  • 20
  • 43
  • And why do you expect your viewModel's onCleared() with the onDestroyView() of the fragment? – Rahul Shukla Nov 06 '19 at 12:59
  • myViewModel lifecycle owner is the fragment. – Sharas Nov 06 '19 at 13:00
  • okay, but it hasn't been destroyed yet. Wait for the onDestroy() call of the fragment. – Rahul Shukla Nov 06 '19 at 13:02
  • I'm not sure you are right, but anyway, it doesn't change the fact that the viewmodel onCleared is not called when I'm navigating to another fragment but when I press the back button it does – Sharas Nov 06 '19 at 13:06
  • With backpressed the fragment is removed on the stack. With naviation to another fragment, the first one is still on the view stack and thus won't be destroyed unitl the device needs memory. – Thommy Nov 06 '19 at 13:11
  • when you navigate from one fragment to another your current fragment goes to backstack that means your view get destroy but instance of fragment remains and in case of back press your current fragment gets destroy. your viewmodel get destroy with `onDestroy()` method of fragment not with `onDestroyView()` – Kalpesh Kulye Nov 06 '19 at 13:14

2 Answers2

0

The framework keeps the ViewModel alive as long as the scope of the activity or fragment is alive. A ViewModel is not destroyed if its owner destroyed for configuration change,such as screen orientation (in this case also the onDestroy() method called.) The new instance of owner reconnects to the existing ViewModel instance. But if we intentionally want to finish the activity,then ViewModel will clear. onClear() method is called before the cleaning occurs. ViewModel is also cleared on onBackPress(). Because in this case, we also finish the activity intentionally.

Decision: ViewModel is cleared when -

  1. onBackPressed called
  2. finish() method called
  3. Activity is shut down by the system due to memory issues.
  • The last part is incorrect. The ViewModel remains in memory until the Lifecycle it's scoped to goes away permanently: in the case of an activity, when it finishes, while in the case of a fragment, when it's detached. – zen_of_kermit Mar 20 '22 at 09:12
0

ViewModel objects are scoped to a Lifecycle. They remain in memory until that Lifecycle object goes away permanently. In the case of an Activity, that's when it is finished, and for a Fragment, when it's detached. See ViewModel Overview for more information.

Without seeing more of your code, it's difficult to answer why onCleared is called on back press and not when the Fragment is destroyed. However, if your ViewModel is tied to the Activity then hitting back might finish the activity and therefore trigger the call to onCleared. Share more of your code if you want a better chance at someone helping you dig deeper.

zen_of_kermit
  • 1,404
  • 2
  • 13
  • 19