Navigation Component — Comparison between viewModels(), activityViewModels() and navGraphViewModels()

Teo
5 min readOct 3, 2021

--

Navigation Component is an amazing tools in Android Jetpack library for every Android developer. It eliminates the complexity to control and monitor all the fragments manually in your code and wired them up in a handy way.

Source from Android Developer Blog

Let’s take an example, imagine in our project will have plenty of screens, such as Login screen, Sign In screen, etc. All these screens are managed by a navigation graph, we can either view them in visual or in XML way. Besides, we can set your destination by dragging at starting fragment to a destination fragment. By doing these, all the fragments in our project are well managed.

Single-Activity Architecture

As Android developer, we always confuse between Activity and Fragment. Basically, Activity is the screen of app’s user interface while Fragment is some sort of reusable portion from your screen. The existence of Fragment is to provide modularity to Activity because Activity is CPU-intensive UI layout and if created multiple activity in our app, our app may consume more CPU usage than usual. Here are the few weakness of Activity:

  1. Weird transition animation between Activities
  2. Difficult to share data between Activities (Intent is not a good way as passing argument is not type-safety)
  3. Difficult to pass arguments from Activity to Fragments.

Based on these weakness, Google announced Single-Activity Architecture where the whole application only host by 1 Activity, the remaining screen as used as fragment.

MVVM — ViewModel

Still remember MVVM? A recommended architecture for modern Android Application. By using Single-Activity Architecture, we have no worry on our data being disposed in ViewModel.

This is because ViewModel is respect to Activity’s lifecycle, which means when its activity get destroyed, the corresponding ViewModel get destroyed as well. By using Single-Activity Architecture, all our data in ViewModel are secured.

However, there is always different use cases when comes to holding data in our ViewModel. For example, what if we only want our ViewModel to be persist in certain fragments? is it we going to reinitialise the whole ViewModel?

The solution is, there are different scopes of ViewModel provided by Android-ktx library. They are:

  1. viewModels()
  2. activityViewModels()
  3. navGraphViewModels()

viewModels()

viewModels() is used to scoped to the fragment where it initialised. When that attached fragment get destroy, viewModels() will also get destroyed.

activityViewModels()

activityViewModels() is pretty self-explanatory. It is used to scoped to its activity and when its activity get destroy, activityViewModels() will be destroyed as well.

navGraphViewModels()

navGraphViewModels() is ViewModel that bind to navigation graph and will persist throughout the entire backstack of that navigation graph. This is how we persist our data throughout certain Fragment and dispose these when exit this navigation graph.

Talk is Cheap, show me code!

Well, I know it is quite hard to understand. I had created a sample project that demonstrate how these viewModels being used and difference between them.

Let’s talk about the demo project. There are 3 TextView and 3 Button, each button will be navigate to each corresponding fragment. Each TextView will be a LiveData observer that matched to each corresponding viewModel.

For each fragment, we will have a navigation linking to them. However, we created a nested graph for navGraphViewModels() as this viewModels will be scoped based on its own navigation graph.

Let’s get our hands dirty!

1. viewModels()

In ViewModelsFragment , we will create vmViewModel that scoped to viewModels() and inside the ViewModel will have a MutableLiveData of sampleText . When we type something, we will update sampleText and instantly display in the view.

When navigate back to MainFragment , ViewModelFragment is destroyed. Since we are using viewModels() , all the data stored in ViewModel is destroyed and no value is displayed at MainFragment .

2. activityViewModels

This time, all the code are the same except we changed viewModels() to activityViewModels() .

and as expected, sampleText ‘s value will be persist since the host activity is not destroyed. Hence, activityViewModels() is very useful to share/communicate between multiple fragments.

3. navGraphViewModels()

For navGraphViewModels() , we will have 2 different fragment in the sub-navGraph and we named the sub-navGraph as navigation-sub_navgraph . By using this id, we declared our navGraphViewModels() with this id, along with a defaultViewModelProviderFactory as we are not doing any constructor-based viewModel.

Here is the result. When we type something and store it in viewModel, both fragment in the sub-navGraph will have the value. However, when navigate back to MainFragment, the backstack of the sub-navGraph is cleared, so as the navGraphViewModels() will be destroyed. When we navigate to a new Fragment, data in navGraphViewModels() will be re-initialised again and scope to the backstack of its navGraph.

navGraphViewModels is very useful when we are creating fragment for some modules and we don’t want these viewModels to be persist throughout the whole activity. Hence, we can create our own custom sub-navGraph with navGraphViewModels() .

Conclusion

Long story short, there are 3 major scoped ViewModels.

  1. viewModels() — scoped to its fragment
  2. activityViewModels() — scoped to its activity
  3. navGraphViewModels() — scoped to its sub-navGraph.

Hope I made this explanation clear! If there are still any question in your mind, feel free to ask in the comment and I will reply ASAP. 😃

Thanks for reading my post and hope you learn something from me. Do comment if you want to know anything more about Android stuff. 🍷

Github: https://github.com/WenLonG12345/NavGraphViewModelProject

--

--

Teo

React & Android Dev, JS & Kotlin Lover, Looking to do more and change the world! 🚀