Я использую dagger.android и хочу ввести ViewModels.С другой стороны, у меня есть ApiModule
, который зависит от контекста активности,
Вот AppComponent
@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
AppModule.class,
ActivityBindingModule.class,
ViewModelModule.class
})
public interface AppComponent extends AndroidInjector<MyApp> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<MyApp> {}
}
ViewModelModule
предоставляет ViewModelProvider.Factory
@Module
abstract class ViewModelModule {
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(MyAppViewModelFactory factory);
}
Вот ActivityBindingModule
:
@Module
abstract class ActivityBindingModule {
//MainActivity
@ActivityScoped
@ContributesAndroidInjector(modules = {
MainActivityModule.class,
ApiModule.class
})
abstract MainActivity contributeMainActivityInjector();
@Module
abstract class MainActivityModule {
@ActivityScoped
@Binds
abstract Activity bindMainActivity(MainActivity activity);
@Binds
@IntoMap
@ViewModelKey(UserViewModel.class)
abstract ViewModel bindUserViewModel(UserViewModel userViewModel);
}
//SecondActivity
@ActivityScoped
@ContributesAndroidInjector(modules = {
SecondActivityModule.class,
ApiModule.class
})
abstract SecondActivity contributeSecondActivityInjector();
@Module
abstract class SecondActivityModule {
@ActivityScoped
@Binds
abstract Activity bindSecondActivity(SecondActivity activity);
@Binds
@IntoMap
@ViewModelKey(DetailViewModel.class)
abstract ViewModel bindDetailViewModel(DetailViewModel detailViewModel);
}
}
У меня есть следующие иерархии инъекций:
MainActivity --inject--> ViewModelProvider.Factory --inject--> MyAppViewModelFactory --inject--> UserViewModel --inject--> UserRepository --inject--> ApiService --inject--> Activity context
SecondActivity --inject--> ViewModelProvider.Factory --inject--> MyAppViewModelFactory --inject--> DetailViewModel --inject--> DetailRepository --inject--> ApiService --inject--> Activity context
Мы предоставляем:
Activity
контекст MainActivityModule
(и SecondActivityModule
) ApiService
в ApiModule
(добавляется в модули каждого действия в ActivityBindingModule
) UserRepository
и DetailRepository
@Singleton
UserViewModel
в MainActivityModule
и DetailViewModel
on SecondActivityModule
MyAppViewModelFactory
is @ Singleton
Вот MyAppViewModelFactory
:
@Singleton
public class MyAppViewModelFactoryimplements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
MyAppViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
this.creators = creators;
}
@SuppressWarnings("unchecked")
@Override
@NonNull
public <T extends ViewModel> T create(@NonNull 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);
}
}
}
Я получил эту ошибку:
error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at
com.example.viewmodels.MyAppViewModelFactory.<init>(creators)
com.example.viewmodels.MyAppViewModelFactory is injected at
com.example.di.ViewModelModule.bindViewModelFactory(factory)
android.arch.lifecycle.ViewModelProvider.Factory is injected at
com.example.activities.MainActivity.viewModelFactory
com.example.activities.MainActivity is injected at
dagger.android.AndroidInjector.inject(T)
component path: com.example.di.AppComponent ? com.example.di.ActivityBindingModule_ContributeMainActivityInjector.MainActivitySubcomponent
Я пытался переместить bindUserViewModel
(с MainActivityModule
) и bindDetailViewModel
(с SecondActivityModule
) на ViewModelModule
, и я получил эту ошибку:
error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] tk.medlynk.medlynk.http.ApiService cannot be provided without an @Provides-annotated method.
com.example.http.ApiService is injected at
com.example.repositories.UserRepository.<init>(apiService)
com.example.repositories.UserRepository is injected at
com.example.viewmodels.UserViewModel.<init>(userRepo)
com.example.viewmodels.UserViewModel is injected at
com.example.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.example.viewmodels.MyAppViewModelFactory.<init>(creators)
com.example.viewmodels.MyAppViewModelFactory is injected at
com.example.di.ViewModelModule.bindViewModelFactory(factory)
android.arch.lifecycle.ViewModelProvider.Factory is injected at
com.example.activities.MainActivity.viewModelFactory
com.example.activities.MainActivity is injected at
dagger.android.AndroidInjector.inject(T)
component path: com.example.di.AppComponent ? com.example.di.ActivityBindingModule_ContributeMainActivityInjector.MainActivitySubcomponent
Что мне здесь не хватает? iosched проект делает то же самое без проблем