Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Hilt to inject a safe-args argument into a viewmodel?

I have found a similar question here. At the time of writing this question there is only this answer avaliable, which does not provide any help to me, and I believe also to the person who asked the question.

I checked the repo which is linked in the answer and it "solves" the problem by creating an init method in the viewmodel and calling it in the Activity/Fragment.

Since the viewmodel has already been injected, this solution does not seem like ideal to me, and I would like to know if there are other options available when using hilt.

like image 564
Ylli Xheladini Avatar asked May 01 '21 19:05

Ylli Xheladini


People also ask

How do you inject ViewModel with Hilt?

Inject ViewModel objects with Hilt Provide a ViewModel by annotating it with @HiltViewModel and using the @Inject annotation in the ViewModel object's constructor. Note: To use Dagger's assisted injection with ViewModels, see the following Github issue.

How do you inject ViewModel in activity?

The koin-android Gradle module introduces a new viewModel DSL keyword that comes in complement of single and factory , to help declare a ViewModel component and bind it to an Android Component lifecycle. Your declared component must at least extends the android.

Should ViewModel be injected?

The viewModels() extension function is provided by androidx KTX . Even if the ViewModel has savedStateHandle or is taking the intent bundle from the Activity, it doesn't need to be explicitly injected in. The viewModels() extension function does all that automatically behind the scene.

What is assisted injection Hilt?

Assisted injection is a dependency injection (DI) pattern that is used to construct an object where some parameters may be provided by the DI framework and others must be passed in at creation time (a.k.a “assisted”) by the user.


1 Answers

As per this comment and the release of AndroidX Hilt 1.0.0-alpha03, Hilt has supported ViewModels that take a SavedStateHandle as a parameter (right alongside your other injected parameters).

This SavedStateHandle is automatically, without you doing anything, populated with the arguments passed to your fragment (i.e., the same arguments you get from requireArguments() and the same arguments that are read by Safe Args).

Therefore in your ViewModel's constructor, you can immediately access those arguments from the SavedStateHandle, without having to do any manual passing of arguments to your ViewModel.

@HiltViewModel
class MainViewModel @Inject constructor(
    val userDataManager: UserDataManager,
    savedStateHandle: SavedStateHandle
) : ViewModel() {
    init {
        // Use the same argName as in your navigation graph
        val yourArgument: String = savedStateHandle["argName"]
        // Now use that argument to load your data, etc.
    }
}

The feature request for Safe Args integration with SavedStateHandle is already fixed and will be part of the upcoming Navigation 2.4.0-alpha01 release. Once that is released, you'd be able to do something like MainFragmentArgs.fromSavedStateHandle(savedStateHandle) to get the same Args class you're currently able to get from by navArgs() within your ViewModel.

like image 144
ianhanniballake Avatar answered Sep 20 '22 04:09

ianhanniballake