Dagger: IllegalArgumentException: 没有绑定到类的注入器工厂 [英] Dagger: IllegalArgumentException: No injector factory bound for Class

查看:47
本文介绍了Dagger: IllegalArgumentException: 没有绑定到类的注入器工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Dagger 2 的新手.我有 2 个活动,我想为这两个活动使用注入的 ViewModel.这是我的 ViewModuleFactory:

@Singleton公共类 ProductViewModelFactory 实现 ViewModelProvider.Factory {私人最终地图<类,提供者<视图模型>>创作者;@注入public ProductViewModelFactory(Map, Provider> creators) {this.creators = 创造者;}@SuppressWarnings("未选中")@覆盖public <T extends ViewModel>T 创建(类 模型类){供应商creator = creators.get(modelClass);如果(创建者 == 空){for (Map.Entry, Provider> entry : creators.entrySet()) {如果 (modelClass.isAssignableFrom(entry.getKey())) {创建者 = entry.getValue();休息;}}}如果(创建者 == 空){throw new IllegalArgumentException("未知视图模型类" + modelClass);}尝试 {返回(T)creator.get();} 捕获(异常 e){抛出新的运行时异常(e);}}}

我的ViewModelModule:

@Module抽象类 ViewModelModule {@绑定@IntoMap@ViewModelKey(ProductListViewModel.class)抽象视图模型 bindProductListViewModel(ProductListViewModel listViewModel);@绑定@IntoMap@ViewModelKey(ProductDetailsViewModel.class)抽象 ViewModel bindProductDetailsViewModel(ProductDetailsViewModel detailsViewModel);@绑定抽象 ViewModelProvider.Factory bindViewModelFactory(ProductViewModelFactory factory);}

我的 ViewModelKey 用于映射:

@Documented@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@地图键@interface ViewModelKey {类价值();}

我的ActivityModule:

@Module公共抽象类 ActivityModule {抽象 ProductListActivity 贡献ProductListActivity();抽象 ProductDetailsActivity 贡献ProductDetailsActivity();}

我的AppModule:

@Module类 AppModule {@提供@单身人士RedMartProductService providerRedMartProductService() {…………}@提供@单身人士ProductListRepository provideProductListRepository(ProductListRepository 存储库){返回存储库;}@提供@单身人士ProductDetailsRepository 提供ProductDetailsRepository(ProductDetailsRepository 存储库) {返回存储库;}}

我的AppComponent:

@Singleton@Component(modules = {AndroidInjectionModule.class, ActivityModule.class, AppModule.class})公共接口 AppComponent {@Component.Builder界面生成器{@绑定实例构建器应用程序(Application application);AppComponent build();}无效注入(MartApplication martApp);}

我的申请:

public class MartApplication extends Application 实现 HasActivityInjector {@注入调度AndroidInjector调度AndroidInjector;@覆盖公共无效 onCreate() {super.onCreate();}@覆盖公共调度AndroidInjector活动注入器(){返回调度AndroidInjector;}}

活动中:

@InjectViewModelProvider.Factory viewModelFactory;......AndroidInjection.inject(活动);//抛出异常ListViewModel = ViewModelProviders.of(this, viewModelFactory).get(ProductListViewModel.class);

它在注入时抛出异常:

java.lang.IllegalArgumentException: 没有为 Class 绑定注入器工厂

谁能帮我找出代码中的问题?

.........................................................

编辑:我按照@azizbekian 尝试使用 ContributesAndroidInjector,但在构建时出现以下错误:

 error: [dagger.android.AndroidInjector.inject(T)] 发现一个依赖循环:com.mymart.repository.ProductListRepository 注入com.mymart.di.AppModule.provideProductListRepository(repository)com.mymart.repository.ProductListRepository 注入com.mymart.viewmodel.ProductListViewModel.(productListRepository)com.mymart.viewmodel.ProductListViewModel 被注入com.mymart.di.ViewModelModule.bindProductListViewModel(listViewModel)java.util.Map,javax.inject.Provider>注射在com.mymart.viewmodel.ProductViewModelFactory.(创建者)com.mymart.viewmodel.ProductViewModelFactory 被注入com.mymart.di.ViewModelModule.bindViewModelFactory(工厂)android.arch.lifecycle.ViewModelProvider.Factory 被注入com.mymart.ui.ProductListActivity.viewModelFactorycom.mymart.ui.ProductListActivity 被注入dagger.android.AndroidInjector.inject(arg0)

编辑 2在所有更改之后,我再次面临异常:

java.lang.RuntimeException: 无法创建应用程序 com.kaushik.myredmart.MartApplication: java.lang.IllegalStateException: com.kaushik.myredmart.di.AppModule 必须设置在 android.app.ActivityThread.handleBindApplication(ActivityThread.java:4710)在 android.app.ActivityThread.-wrap1(ActivityThread.java)在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)在 android.os.Handler.dispatchMessage(Handler.java:102)在 android.os.Looper.loop(Looper.java:148)在 android.app.ActivityThread.main(ActivityThread.java:5417)在 java.lang.reflect.Method.invoke(Native Method)在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)引起:java.lang.IllegalStateException:com.kaushik.myredmart.di.AppModule 必须设置在 com.kaushik.myredmart.di.DaggerAppComponent$Builder.build(DaggerAppComponent.java:180)在 com.kaushik.myredmart.di.AppInjector.init(AppInjector.java:30)在 com.kaushik.myredmart.MartApplication.onCreate(MartApplication.java:28)在 android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1013)在 android.app.ActivityThread.handleBindApplication(ActivityThread.java:4707)在 android.app.ActivityThread.-wrap1(ActivityThread.java)在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)在 android.os.Handler.dispatchMessage(Handler.java:102)在 android.os.Looper.loop(Looper.java:148)在 android.app.ActivityThread.main(ActivityThread.java:5417)在 java.lang.reflect.Method.invoke(Native Method)

解决方案

相信你忘了放 @ContributesAndroidInjector 注解:

<前><代码>@模块公共抽象类 ActivityModule {@ContributesAndroidInjector抽象 ProductListActivity 贡献ProductListActivity();@ContributesAndroidInjector抽象 ProductDetailsActivity 贡献ProductDetailsActivity();}

并在 AppModule 中包含 ViewModelModule:

<前><代码>@Module(includes = ViewModelModule.class)类 AppModule {...}

<小时>

看看你写的这段代码:

@Provides@单身人士ProductListRepository provideProductListRepository(ProductListRepository 存储库){返回存储库;}

你期望发生什么?你告诉 dagger 嘿,dagger,每当我要求你提供我 ProductListRepository 然后使用 ProductListRepository 创建(返回)那个对象".那行不通.

很可能你想要的是嘿,匕首,每当我要求你提供一个 ProductListRepository 的实现然后使用 ProductListRepositoryImpl 创建(返回)那个对象>":

@Provides@单身人士ProductListRepository provideProductListRepository(ProductListRepositoryImpl 存储库){返回存储库;}

可以替换为以下内容:

@Binds@单身人士抽象 ProductListRepository provideProductListRepository(ProductListRepositoryImpl 存储库);

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);
        }
    }
}

My 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);
}

My ViewModelKey for mapping:

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {
    Class<? extends ViewModel> value();
}

My ActivityModule :

@Module
public abstract class ActivityModule {
    abstract ProductListActivity contributeProductListActivity();
    abstract ProductDetailsActivity contributeProductDetailsActivity();
}

My AppModule:

@Module
class AppModule {

@Provides
    @Singleton
    RedMartProductService provideRedMartProductService() {
        ........
    }

    @Provides
    @Singleton
    ProductListRepository provideProductListRepository(ProductListRepository repository) {
        return repository;
    }

    @Provides
    @Singleton
    ProductDetailsRepository provideProductDetailsRepository(ProductDetailsRepository repository) {
        return repository;
    }
}

My 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);
}

My Application:

public class MartApplication extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public DispatchingAndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}

In Activity:

@Inject
ViewModelProvider.Factory viewModelFactory;
.......
AndroidInjection.inject(activity); // Throwing exception
ListViewModel = ViewModelProviders.of(this, viewModelFactory).get(ProductListViewModel.class);

It is throwing an exception on inject:

java.lang.IllegalArgumentException: No injector factory bound for Class<com.mymart.ui.ProductListActivity>

Can anyone help me identify the problem in my code?

.......................................................................

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)

Edit 2 After 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)

解决方案

I believe you have forgot to put @ContributesAndroidInjector annotation:


    @Module
    public abstract class ActivityModule {
        @ContributesAndroidInjector
        abstract ProductListActivity contributeProductListActivity();
        @ContributesAndroidInjector
        abstract ProductDetailsActivity contributeProductDetailsActivity();
    }

And include ViewModelModule within AppModule:


    @Module(includes = ViewModelModule.class)
    class AppModule {
        ...
    }


See this code that you have wrote:

@Provides
@Singleton
ProductListRepository provideProductListRepository(ProductListRepository repository) {
    return repository;
}

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.

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;
}

Which may be substituted with following:

@Binds
@Singleton
abstract ProductListRepository provideProductListRepository(ProductListRepositoryImpl repository);

这篇关于Dagger: IllegalArgumentException: 没有绑定到类的注入器工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆