Skip to content

Hilt and ViewModel initialization with Navigation Component arguments #692

@langsmith

Description

@langsmith

tldr; How do I initialize a Mavericks State with Navigation Component arguments when the fragment's ViewModel is using hiltMavericksViewModelFactory ?

I'm trying to figure out how to blend the use of this Mavericks library (version 3.0.6), Hilt, and Navigation Component arguments. I'm not using Compose. I'm using Views. My app is single activity, multiple fragments.

I've also seen the README and various example files within https://github.com/airbnb/mavericks/tree/main/sample-hilt.


My Gradle setup:

val navigationVersion = "2.7.2"
implementation("androidx.navigation:navigation-fragment-ktx:$navigationVersion")
implementation("androidx.navigation:navigation-ui-ktx:$navigationVersion")

val mavericksVersion = "3.0.6"
implementation ("com.airbnb.android:mavericks:$mavericksVersion")
implementation ("com.airbnb.android:mavericks-testing:$mavericksVersion")
implementation ("com.airbnb.android:mavericks-navigation:$mavericksVersion")
    
val hiltVersion = "2.48"
implementation ("com.google.dagger:hilt-android:$hiltVersion")
kapt ("com.google.dagger:hilt-compiler:$hiltVersion")
implementation("androidx.hilt:hilt-navigation-fragment:1.0.0")    

HomeState in the HomeViewModel is:

data class HomeState(
    val userFullName: String = "",
    val paymentList: Async<List<Payment>> = Uninitialized,
    val coarseLocationPermissionGranted: Boolean = false,
    val deviceLastLocationCoordinates: Pair<Double, Double> = Pair(0.0, 0.0),
    val count: Int = 0
) : MavericksState
Screenshot 2023-09-05 at 10 02 38 AM

I had Mavericks working just fine before I decided to try to install Hilt.

companion object : MavericksViewModelFactory<HomeFragmentViewModel, HomeState> {

        override fun initialState(viewModelContext: ViewModelContext): HomeState {
            val homeFragment: HomeFragment = (viewModelContext as FragmentViewModelContext).fragment()
            val userFullName = homeFragment.arguments?.getString(LoginFragment.SESSION_FULL_NAME_KEY).orEmpty()
            return HomeState(userFullName = userFullName)
        }

        override fun create(viewModelContext: ViewModelContext, state: HomeState): HomeFragmentViewModel {
            return HomeFragmentViewModel(state)
        }
    }
Screenshot 2023-09-04 at 10 36 16 AM

My setup is the following after I dove into setting up Hilt. It works but I'm not initializing the ViewModel with any Navigation Component arguments:

@AssistedFactory interface Factory : AssistedViewModelFactory<HomeFragmentViewModel, HomeState> {
        override fun create(state: HomeState): HomeFragmentViewModel
    }

    /* 
    companion object : MavericksViewModelFactory<HomeFragmentViewModel, HomeState> {
        override fun initialState(viewModelContext: ViewModelContext): HomeState {
            val homeFragment: HomeFragment = (viewModelContext as FragmentViewModelContext).fragment()
            val userFullName = homeFragment.arguments?.getString(LoginFragment.SESSION_FULL_NAME_KEY).orEmpty()
            return HomeState(userFullName = userFullName)
        }
    }
    */

    companion object : MavericksViewModelFactory<HomeFragmentViewModel, HomeState> by hiltMavericksViewModelFactory()
Screenshot 2023-09-04 at 10 35 37 AM

As expected, I get the crash below if I experiment by commenting out the hiltMavericksViewModelFactory() companion object setup

Screenshot 2023-09-04 at 10 48 57 AM Screenshot 2023-09-05 at 10 08 26 AM

Ignoring the crash for a moment, my overall question again is how I would initialize the HomeState with that initial userFullName value from the Navigation Component argument bundle?

I see mention of viewModelContext in the HiltMavericksViewModelFactory class, so do I need to somehow adjust that HiltMavericksViewModelFactory class?

I haven't tried it, but would a hack be to pass the arguments (bundle) from the fragment to the ViewModel in the fragment's onCreate() or onCreateView()?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions