Search code examples
androidandroidxandroid-viewmodeldagger-hilt

Access deep-link parameters from an Android View Model's injected SavedStateHandle


How would I access data from a deep-link inside of an Android's Architecture Components ViewModel at its init-time. I have access to extras provided in the intent's Bundle (intent.extras) through a Hilt-injected SavedStateHandle, but when opening the Activity through a deep-link, I only have a URI (intent.data) on the Activity level, and nothing in the ViewModel.

As an example, say I'm opening my activity through something like my-app://profile?id=123, how would I get access to that 123 ID from an AAC ViewModel at init-time?


Solution

  • One solution to this could be to intercept the creation of the view model. The ComponentActivity.viewModels() extension allows changing the CreationExtras, which will get passed to the SavedStateHandle:

    public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
        noinline extrasProducer: (() -> CreationExtras)? = null,
        noinline factoryProducer: (() -> Factory)? = null
    ): Lazy<VM>
    

    By default, a ComponentActivity creates extras for its view models through getDefaultViewModelCreationExtras(), which only grabs extras from the intent, but passing a extrasProducer, we can inject more things:

    private val viewModel: SomeViewModel by viewModels(
        extrasProducer = {
            val extras = MutableCreationExtras(defaultViewModelCreationExtras)
    
            intent?.data?.getQueryParameter("id")?.let { queryParamId ->
                extras[DEFAULT_ARGS_KEY] = bundleOf("id" to queryParamId)
            }
    
            extras
        }
    )