Reputation: 589
I am trying to inject viewmodel with help of a common ViewModelProviderFactory in dagger2. (This is my first app with dagger and architecure components) This is the error i get when i build the code.
Error:(26, 10) error: java.util.Map,javax.inject.Provider> cannot be provided without an @Provides-annotated method.
Here is the code i use
ViewModelProviderFactory
@PerActivity
public class ViewModelProviderFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
public ViewModelProviderFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
this.creators = creators;
}
@SuppressWarnings("unchecked")
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
Provider<? extends ViewModel> creator = creators.get(modelClass);
if (creator == null) {
for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
if (modelClass.isAssignableFrom(entry.getKey())) {
creator = entry.getValue();
break;
}
}
}
if (creator == null) {
throw new IllegalArgumentException("unknown model class " + modelClass);
}
try {
return (T) creator.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
ViewModelModule
@Module
public abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(HomeViewModel.class)
abstract ViewModel bindHomeViewModel(HomeViewModel homeViewModel);
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelProviderFactory factory);
}
ApplicationComponent
@Singleton
@Component(modules = {ApplicationModule.class, ViewModelModule.class})
public interface ApplicationComponent {
void inject(BaseApp app);
@ApplicationContext
Context getContext();
Application getApplication();
WebService getWebService();
PreferencesHandler getPreferencesHandler();
InternetUtils getInternetUtils();
}
ActivityComponent
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
void inject(SampleListActivity sampleListActivity);
void inject(HomeActivity homeActivity);
}
ViewModelKey
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface ViewModelKey {
Class<? extends ViewModel> value();
}
In my activity i use this code
@Inject
ViewModelProviderFactory mViewModelFactory;
........
oncreate(){
...
homeViewModel = ViewModelProviders.of(this,mViewModelFactory).get(HomeViewModel.class);
.......
}
Upvotes: 3
Views: 978
Reputation: 34532
Your ActivityComponent
is a Component
(not a SubComponent) with a dependency on ApplicationComponent
, so it has no access to the Map set up in the AppComponent.
Either switch to using a SubComponent
for your ActivityComponent
, or make sure to include a provision method for Map<Class<? extends ViewModel>, Provider<ViewModel>>
in your AppComponent so that dependent components can access it.
interface AppComponent {
// ..
Map<Class<? extends ViewModel>, Provider<ViewModel>> creators();
}
Upvotes: 3