A step by step guide on how to use Nav-graph Scoped ViewModels

Sanmi Aderibigbe
Sprinthub Engineering
4 min readApr 29, 2020

Two years ago, there was a revolutionary change in the way we Android developers develop our apps. This came with the release of Android architecture components. Google also proposed the De Facto architecture for developing modern-day android applications, MVVM with a single Activity. Amongst this collection of libraries are my personal favourites; the navigation components and viewmodel.

In this article, I will show you how to share viewmodels between fragments in Google’s proposed MVVM with a single Activity.

WARNING:I won’t be going deep into Android architecture components, MVVM, single activity. If you’re not familiar with these technologies, Google has a ton of resources on them. Please, check them out; otherwise, this article won’t be understandable 😒.

THE MOTIVATION

Yes, using Google’s proposed architecture and libraries does make development much easier but sometimes you are left wondering, “How do I go about this?” This happened when I tried sharing my viewmodels between fragments using Google’s proposed architecture. I know what you’re thinking, “That’s easy! Scope your viewmodel to an Activity and move on with your life.” But the thing about single activity is that there is only one single activity.

I know, right? Mind blowing stuff.

Essentially, scoping your viewmodel to the only activity in your app makes that viewmodel a singleton that would remain as long as your app is alive.

Let’s say you’re making an order selection flow and you decide to scope your viewmodels to the activity. Since your order selection viewmodel life cycle is scoped to that of an Activity, the viewmodel will never get destroyed, but you want a new order selection view model whenever the user starts a new order selection process. You could manually delete all the data held by the viewmodel when the user completes the order selection process — but that’s very error prone. And also, scoping all your viewmodels to the activity would make your app consume more memory than necessary.

You really don’t have to do all that. There is a better way to share view models in single activity architecture.

With the release of navigation components V 2.1.0, you can now create view models scoped to a navigation graph. It’s actually pretty simple and painless to do and I’ll show you how.

1. Create a nested navigation graph that contains all fragments you’d like to share viewModels with. Nested graphs are useful to organize and reuse sections of your app’s UI, such as a self-contained order selection flow.

2. Give the nested navigation graph an ID. Let’s call it order_selection_nav_graph

3a For Kotlin users, there is a sweet new extension function called navGraphViewModels. navGraphViewModels is a kotlin extension function for fragments that creates nav graph scoped view models. It accepts two parameters: a nav graph ID and also a viewmodel factory.

You can simply write:

Val order selection by navGraphViewModels(R.id.order_selection_nav_graph).

Remember, order_selection_nav_graph is the name of the nested nav graph we created earlier.

3b For Java users, switch to Kotlin, there’s nothing for you 😛. Just kidding. You can create nav graph scoped viewmodels in Java by first getting the viewmodel store. A viewmodel store is basically just a container that stores viewmodels.

ViewmodelStore store = navcontroller.getViewModelStore(R.id.order_selection_nav_graph)

Then get the viewModel by passing the viewModelStore into a viewmodelProvider.

OrderSelection ViewModel = new ViewModelProvider(store)

Conclusion

See, I told you it was super simple. The ViewModel will live until the containing host and its ViewModelStore are cleared or the navigation graph is popped off the back stack. Basically, a new viewmodel is created every time the user starts the order selection process and the viewmodel is destroyed when the user completes the process. You don’t have to hack the viewmodel by manually clearing data and consuming unnecessary memory by scoping all your viewmodels to the activity.

You can check out my repo below for the sample code.

https://github.com/sprinthubmobile/ByNavGraphViewModelsSampleCode

--

--