[GithubBrowserSample] Recommended way to inject dynamic parameters to ViewModel using Dagger 2
See original GitHub issueHi everyone! Thanks for great examples. I’m just wondering what method you recommend to inject dynamic parameters into ViewModel using Dagger 2? Currently in the GithubBrowserSample such parameters are injected by hand using setters:
userViewModel = ViewModelProviders.of(this, viewModelFactory).get(UserViewModel.class);
userViewModel.setLogin(getArguments().getString(LOGIN_KEY));
I’ve tried to move login String to the UserViewModel constructor but unfortunately, it caused the problem:
Error:(35, 8) error: [dagger.android.AndroidInjector.inject(T)] @javax.inject.Named("login") java.lang.String cannot be provided without an @Provides-annotated method.
@javax.inject.Named("login") java.lang.String is injected at
com.android.example.github.ui.user.UserViewModel.<init>(…, loginString)
com.android.example.github.ui.user.UserViewModel is injected at
com.android.example.github.di.ViewModelModule.bindUserViewModel(userViewModel)
java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at
com.android.example.github.viewmodel.GithubViewModelFactory.<init>(creators)
com.android.example.github.viewmodel.GithubViewModelFactory is injected at
com.android.example.github.di.ViewModelModule.bindViewModelFactory(factory)
android.arch.lifecycle.ViewModelProvider.Factory is injected at
com.android.example.github.ui.repo.RepoFragment.viewModelFactory
com.android.example.github.ui.repo.RepoFragment is injected at
dagger.android.AndroidInjector.inject(arg0)
So… what is your recommended way to pass dynamic parameters to the constructor instead of setters? I see one solution - using separate ViewModelFactory implementation per each ViewModel. What do you think about it? Do you have any other recommendations?
Issue Analytics
- State:
- Created 6 years ago
- Reactions:29
- Comments:26
Top Results From Across the Web
How To Inject ViewModel With Dagger & What Might Go Wrong
There are several methods. The easiest way is to inject view model providers into a factory and map them manually: Add this factory...
Read more >dagger 2 - How to use AssistedInject to pass dynamic value as ...
This is the simple ViewModel I used for testing ViewModel injection. WeatherViewModel class WeatherViewModel @Inject constructor(val repository: ...
Read more >ViewModel with Dagger2 (Android Architecture Components)
In this story I want to share some light on how you can use ViewModel (Android ... For @Inject with dynamic parameters read...
Read more >Understanding Dagger 2 Multibindings + ViewModel
Many of us, when started learning how to use the new ViewModel class had a look at the GithubBrowserSample example on GitHub (this...
Read more >Injecting Android ViewModels With Dagger2 in a Clean ...
Today, we're going to learn how to use ViewModel in clean architecture and build a dependency injection framework with Dagger2 so that we ......
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@radzio I feel like the best way to transfer data from View to ViewModel is by using those setter methods. In order for MVVM architecture to work, the View must push commands to the ViewModel and receive data from a binding of some sort. By allowing the ViewModel to “pull” data from the View (through a Dagger injection), the architecture is broken and you run into problems.
You also have to keep in mind the lifecycle of your components. ViewModels exist for a long time, so they can’t reference any views. I think Dagger is not the right tool for the job, and that the
userViewModel.setLogin(getArguments().getString(LOGIN_KEY));
that you want to get rid of is actually helping to clearly divide the architecture into Model, ViewModel, and View.@radzio the idea is to inject the ViewModel.Factory that’ll be responsible for creating the ViewModel
A possible approach is to provide the ViewModelProvider.Factory in each Activity/Fragment module, which you can specify in the BindingsModule. The problem is the verbosity needed to create a new screen: Activity + ActivityModule + ViewModel + ViewModelProvider.Factory with duplicated code (as you’ll see).
As an example, this’d be the ActivityModule
This is the ViewModel + ViewModelProvider.Factory
And then, the Activity
There must be a better way, but it’s what I’m using.
Like this, it’s easy to provide the dependencies when testing ViewModels in isolation.