【问题标题】:Dagger: IllegalArgumentException: No injector factory bound for Class匕首:IllegalArgumentException:没有注入器工厂绑定到类
【发布时间】:2018-01-01 18:22:40
【问题描述】:

我是 Dagger 2 的新手。我有 2 个活动,我想对两者都使用注入的 ViewModel。这是我的 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>

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

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

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

    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 经过所有更改,我再次面临异常:

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)

【问题讨论】:

    标签: android dependency-injection dagger-2 dagger


    【解决方案1】:

    对于这个错误:“Dagger: IllegalArgumentException: No injector factory bound for Class

    如果您将 Navigation ComponentSingle Activity 一起使用,您会看到此错误。

    你应该怎么做?

    请检查您的 @Module abstract class FragmentProvider { ... },因为您需要在其中添加 Fragment 作为 Contribute。

    @Module
    abstract class FragmentProvider {
    
      @ContributesAndroidInjector // <- Do not forget this line.
      abstract fun contributeYourNewFragment(): YourNewFragment
    }
    

    【讨论】:

      【解决方案2】:

      Dagger2 错误比 dagger1 更直接,但它会根据 dagger 在编译时首先遇到的问题逐个弹出。

      您的解决方案不仅面临上述错误:

      • 第一个错误:Dagger: IllegalArgumentException: No injector factory bound for Class

      那是因为你在 ActivityModule 中为 dagger 提供了活动,而没有添加注释 @ContributesAndroidInjector

      此注解必须应用于返回具体 Android 框架类型的 Module 中的抽象方法。”即Activity/Fragment等

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

      Ref

      • 第二个错误:java.lang.IllegalStateException:必须设置 AppModule 在 DaggerAppComponent$Builder.build(DaggerAppComponent.java:180)

      如果您的 AppModule 没有任何默认构造函数,则 Dagger 无法创建 AppModule 的实例。所以创建一个 AppModule 实例并将其设置为 Dagger graph。

       mComponent = DaggerXComponent.builder()
          .appModule(new AppModule(....)) // create appModule instance
          .build();
      

      如果模块没有任何用户定义的构造函数,那么 Dagger 会在需要时通过默认构造函数自动创建一个实例。

      找到这个answer

      【讨论】:

        【解决方案3】:

        相信你忘记放@ContributesAndroidInjector注解了:

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

        并在AppModule 中包含ViewModelModule

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

        看看你写的这段代码:

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

        你期望会发生什么?你是在告诉 dagger “嘿,dagger,每当我要求你提供ProductListRepository 然后使用ProductListRepository 创建(返回)该对象”。那是行不通的。

        您的意图很可能是“嘿,匕首,每当我要求您提供ProductListRepository 的实现时,然后使用ProductListRepositoryImpl 创建(返回)该对象”

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

        可以用以下代替:

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

        【讨论】:

        • 我试过了。请检查我上面编辑的部分并指导。
        • 我跟着你,它导致了一个依赖循环。请指教。
        • 添加到上面的编辑部分。请检查@azizbekian
        • 感谢您的解释。依赖问题已解决,但运行时出现异常:无法创建应用程序 com.mymart.MartApplication: java.lang.IllegalStateException: com.mymart.di.AppModule 必须设置
        • 查看一些教程。你有很多问题。
        【解决方案4】:

        使用@contrubutesAndroidInjector 需要额外的annotationProcessor。

        将此行添加到您的 gradle 构建文件中:

        annotationProcessor 'com.google.dagger:dagger-android-processor:2.11'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-20
          • 2016-10-01
          • 1970-01-01
          相关资源
          最近更新 更多