In Android Compose navigation, navigation arguments are populated in SavedStateHandle
which can then be accessed in a ViewModel
. I have done this in practice and implementation is well outlined here: https://stackoverflow.com/a/69145748/12385518.
My problem is I cannot find any documentation on why/how this is happening. In fact I cannot even find official documentation that even mention navigation arguments being in SavedStateHandle
at all. I would love to read more about this. I have read these documents (and more) but found nothing on the topic:
https://developer.android.com/topic/libraries/architecture/viewmodel-savedstate https://developer.android.com/reference/androidx/lifecycle/SavedStateHandled
It seems to be a very nice technique for passing around navigation arguments, however since it isn't mentioned anywhere I am considering transitioning to another technique.
Here's how navigation arguments are passed to a ViewModel
.
When you call NavController.navigate(route, args)
a NavBackStackEntry
is created (source).
NavBackStackEntry
creates a SavedStateViewModelFactory
which, as its name suggests, is a factory for creating ViewModel
s with a SavedStateHandle
(source).
NavBackStackEntry
implements HasDefaultViewModelProviderFactory
and exposes its factory from the previous step via the defaultViewModelProviderFactory
property (source).
Crucially, HasDefaultViewModelProviderFactory
also has another property: defaultViewModelCreationExtras
. This contains extra data fields which are used when constructing a ViewModel
. The navigation arguments are stored here (source).
When a viewModel
creation method, such as hiltViewModel
, is called it will check whether the ViewModelStoreOwner
(in this case the NavBackStackEntry
) implements HasDefaultViewModelProviderFactory
. If it does, then it'll pass those extras (the navigation arguments) to the view model factory (source).
The view model factory, in this case SavedStateViewModelFactory
, then creates the SavedStateHandle
, populates it with the navigation arguments (the extras), and supplies it to a newly created ViewModel
so it has access to them (source).