问题描述
我是Dagger 2的新手.我有2个Activity,我想同时使用这两个注入的ViewModel.这是我的 ViewModuleFactory :
I am new to Dagger 2. I have 2 Activities, I want to use injected ViewModel for both. Here is my ViewModuleFactory :
@Singleton
public class ProductViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
public ProductViewModelFactory(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 viewmodel class " + modelClass);
}
try {
return (T) creator.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
我的 ViewModelModule :
@Module
abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(ProductListViewModel.class)
abstract ViewModel bindProductListViewModel(ProductListViewModel listViewModel);
@Binds
@IntoMap
@ViewModelKey(ProductDetailsViewModel.class)
abstract ViewModel bindProductDetailsViewModel(ProductDetailsViewModel detailsViewModel);
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ProductViewModelFactory factory);
}
我的 ViewModelKey 用于映射:
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {
Class<? extends ViewModel> value();
}
我的 ActivityModule :
@Module
public abstract class ActivityModule {
abstract ProductListActivity contributeProductListActivity();
abstract ProductDetailsActivity contributeProductDetailsActivity();
}
我的 AppModule :
@Module
class AppModule {
@Provides
@Singleton
RedMartProductService provideRedMartProductService() {
........
}
@Provides
@Singleton
ProductListRepository provideProductListRepository(ProductListRepository repository) {
return repository;
}
@Provides
@Singleton
ProductDetailsRepository provideProductDetailsRepository(ProductDetailsRepository repository) {
return repository;
}
}
我的 AppComponent :
@Singleton
@Component(modules = {AndroidInjectionModule.class, ActivityModule.class, AppModule.class})
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
AppComponent build();
}
void inject(MartApplication martApp);
}
我的应用:
public class MartApplication extends Application implements HasActivityInjector {
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
@Override
public void onCreate() {
super.onCreate();
}
@Override
public DispatchingAndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
}
在活动中:
@Inject
ViewModelProvider.Factory viewModelFactory;
.......
AndroidInjection.inject(activity); // Throwing exception
ListViewModel = ViewModelProviders.of(this, viewModelFactory).get(ProductListViewModel.class);
它在注入时引发异常:
java.lang.IllegalArgumentException: No injector factory bound for Class<com.mymart.ui.ProductListActivity>
任何人都可以帮助我确定代码中的问题吗?
Can anyone help me identify the problem in my code?
............................................... ........................
.......................................................................
编辑:我按照@azizbekian尝试使用ContributesAndroidInjector
,但是在构建时导致以下错误:
Edit: I tried with ContributesAndroidInjector
as per @azizbekian, but it resulted following error on build:
error: [dagger.android.AndroidInjector.inject(T)] Found a dependency cycle:
com.mymart.repository.ProductListRepository is injected at
com.mymart.di.AppModule.provideProductListRepository(repository)
com.mymart.repository.ProductListRepository is injected at
com.mymart.viewmodel.ProductListViewModel.<init>(productListRepository)
com.mymart.viewmodel.ProductListViewModel is injected at
com.mymart.di.ViewModelModule.bindProductListViewModel(listViewModel)
java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at
com.mymart.viewmodel.ProductViewModelFactory.<init>(creators)
com.mymart.viewmodel.ProductViewModelFactory is injected at
com.mymart.di.ViewModelModule.bindViewModelFactory(factory)
android.arch.lifecycle.ViewModelProvider.Factory is injected at
com.mymart.ui.ProductListActivity.viewModelFactory
com.mymart.ui.ProductListActivity is injected at
dagger.android.AndroidInjector.inject(arg0)
编辑2 经过所有更改后,我再次遇到异常:
Edit 2After all changes, I am facing again exception:
java.lang.RuntimeException: Unable to create application com.kaushik.myredmart.MartApplication: java.lang.IllegalStateException: com.kaushik.myredmart.di.AppModule must be set
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4710)
at android.app.ActivityThread.-wrap1(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: com.kaushik.myredmart.di.AppModule must be set
at com.kaushik.myredmart.di.DaggerAppComponent$Builder.build(DaggerAppComponent.java:180)
at com.kaushik.myredmart.di.AppInjector.init(AppInjector.java:30)
at com.kaushik.myredmart.MartApplication.onCreate(MartApplication.java:28)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1013)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4707)
at android.app.ActivityThread.-wrap1(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
推荐答案
我相信您忘记了放置@ContributesAndroidInjector
批注:
I believe you have forgot to put @ContributesAndroidInjector
annotation:
@Module
public abstract class ActivityModule {
@ContributesAndroidInjector
abstract ProductListActivity contributeProductListActivity();
@ContributesAndroidInjector
abstract ProductDetailsActivity contributeProductDetailsActivity();
}
并将ViewModelModule
包含在AppModule
中:
@Module(includes = ViewModelModule.class)
class AppModule {
...
}
请参阅您编写的以下代码:
See this code that you have wrote:
@Provides
@Singleton
ProductListRepository provideProductListRepository(ProductListRepository repository) {
return repository;
}
您期望发生什么?您是在告诉匕首嘿,匕首,每当我要求您提供ProductListRepository
然后使用ProductListRepository
" 创建(返回)该对象时.那是行不通的.
What do you expect to happen? You are telling dagger "hey, dagger, whenever I ask you to provide me ProductListRepository
then create(return) that object using ProductListRepository
". That's not gonna work out.
您可能想要的是,匕首,每当我要求您提供ProductListRepository
的实现,然后使用ProductListRepositoryImpl
" 创建(返回)该对象:
Most possibly what you intended was "hey, dagger, whenever I ask you to provide me an implementation of ProductListRepository
then create(return) that object using ProductListRepositoryImpl
":
@Provides
@Singleton
ProductListRepository provideProductListRepository(ProductListRepositoryImpl repository) {
return repository;
}
可以用以下内容代替:
@Binds
@Singleton
abstract ProductListRepository provideProductListRepository(ProductListRepositoryImpl repository);
这篇关于匕首:IllegalArgumentException:没有为类绑定的注射器工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!