Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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)
like image 448
Rafael Souza Avatar asked Sep 12 '25 14:09

Rafael Souza


2 Answers

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

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

like image 100
Yvgen Avatar answered Sep 15 '25 04:09

Yvgen


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.

like image 41
Mattia Ferigutti Avatar answered Sep 15 '25 03:09

Mattia Ferigutti