How to pass parameter to viewmodel constructor using HiltViewModel library with jetpack compose
Asked Answered
G

2

23

How to pass parameter to viewmodel constructor using HiltViewModel library with jetpack compose My code:

@HiltViewModel
class GetPurchaseViewModel @Inject constructor(val id:Long) : ViewModel() {
    private val service= RestModule
    var state = MutableStateFlow<State>(State.START)

    init{
        get(id)
    }

    private fun get(id:Long){
        viewModelScope.launch {
            state.value = State.LOADING
            try {
                val users = withContext(Dispatchers.IO) {

                    service.getIntance().getPurchase(id)
                }

                state.value = State.SUCCESLISTPURCHASE(users)
            } catch (e: Exception) {
                state.value = State.FAILURE(message = e.localizedMessage!!)
            }
        }
    }

}

my call in my composable function :

val model:GetPurchaseViewModel=hiltViewModel(idUser)
Gandy answered 5/1, 2022 at 0:43 Comment(6)
Depending on where that id comes from, you could use the savedStateHandle in the viewmodel, it gets pre-populated with the navigation arguments if you use the navigation artifact.Entrap
do you have any easy examples of doing this? or some site that explainsGandy
I just put together a quick sample here: github.com/fvilarino/Navigation-SampleEntrap
Does this answer your question? How to pass id and application to a viewModel/viewModelFactory in Jetpack Compose?Copt
Does this answer your question? How to use Hilt to inject a safe-args argument into a viewmodel?Sanhedrin
The short answer is if you place the arg in a NavHost argument, it will auto-magically pass to the SavedStateHandle - see answer hereDistraught
S
4

I would recommend you to use @AssistedInject, here is official documentation

Also please take a look at this issue [AssistedInject] Integration with @HiltViewModel #2287

Severen answered 27/8, 2023 at 18:22 Comment(0)
S
0

A Simpler Way

Starting from androidx.navigation:navigation-compose:2.8.0-alpha08 the Jetpack Compose team has implemented a new way of navigating between screens using Serializable classes.

Let me take the example from Navigation docs to show you how simpler it's passing data now:

// Define a home destination that doesn't take any arguments
@Serializable
object Home

// Define a profile destination that takes an ID
@Serializable
data class Profile(val id: String) {
  companion object {
    fun from(savedStateHandle: SavedStateHandle) =
      savedStateHandle.toRoute<Profile>()
  }
}

// Now define your NavHost using type safe objects
NavHost(navController, startDestination = Home) {
  composable<Home> {
    HomeScreen(onNavigateToProfile = { id ->
      navController.navigate(Profile(id))
    })
  }
  composable<Profile> {
    ProfileScreen()
  }
}

Now instead of getting the value inside the Profile destination and passing it to ProfileScreen and then passing it to ProfileViewModel, we can get the value directly inside ProfileViewModel and skip all the unnecessary steps.

@HiltViewModel
class ProfileViewModel @Inject constructor(
  savedStateHandle: SavedStateHandle
) {
  private val args = Profile.from(savedStateHandle)

}

For me this approach is much cleaner since we usually don't use the the value, in this case the id, directly inside the composable. But we need to do some operation first, like getting the real Profile object from the id, and then pass it back to ProfileScreen.

I give all the credits for this answer to edgarmiro.

Stasiastasis answered 18/7, 2024 at 13:1 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.