代码之家  ›  专栏  ›  技术社区  ›  silentsudo

Dagger2 Multibinding[dagger.android.AndroidInjector.inject(T)]发现依赖循环:

  •  0
  • silentsudo  · 技术社区  · 8 年前

    我试图复制ViewModelFactory对演示者类所做的操作,下面是我的Dagger2代码

    public class App extends DaggerApplication { //Support import
        @Override
        protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
            return DaggerAppComponent.builder().create(this);
        }
    }
    
    
    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @MapKey
    public @interface PresenterKey {
        Class<? extends PresenterClass> value();
    }
    
        @Module
    public abstract class PresenterModule {
    
        @Binds
        @IntoMap
        @PresenterKey(AuthPresenterImpl.class)
        abstract PresenterClass bindsAuthPresenterImpl(AuthPresenterImpl authViewModel);
    
        @Binds
        abstract PresenterFactory bindsPresenterFactory(PresenterFactory viewModelFactory);
    }
    
    
    @Singleton
    public class PresenterFactory {
        private final Map<Class<? extends PresenterClass>, Provider<PresenterClass>> creators;
    
        @Inject
        public PresenterFactory(Map<Class<? extends PresenterClass>, Provider<PresenterClass>> creators) {
            this.creators = creators;
        }
    
        @SuppressWarnings("unchecked")
        public <T extends PresenterClass> T create(Class<T> modelClass) {
            Provider<? extends PresenterClass> creator = creators.get(modelClass);
            if (creator == null) {
                for (Map.Entry<Class<? extends PresenterClass>, Provider<PresenterClass>> 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);
            }
        }
    }
    

    当我尝试构建时,我会得到错误

        import in.silentsudo.authflow.di.modules.DaggerAppComponent;
                                            ^
      symbol:   class DaggerAppComponent
      location: package in.silentsudo.authflow.di.modules
    /path/to/project/app/src/main/java/in/silentsudo/authflow/di/modules/AppComponent.java:17: error: [Dagger/BindingCycle] [dagger.android.AndroidInjector.inject(T)] Found a dependency cycle:
    public interface AppComponent extends AndroidInjector<AuthFlow> {
           ^
          in.silentsudo.authflow.viewmodels.PresenterFactory is injected at
              in.silentsudo.authflow.di.modules.PresenterModule.bindsPresenterFactory(presenterFactory)
          in.silentsudo.authflow.viewmodels.PresenterFactory is injected at
              in.silentsudo.authflow.AbstractActivity.factory
          in.silentsudo.authflow.auth.AuthActivity is injected at
              dagger.android.AndroidInjector.inject(T)
      component path: in.silentsudo.authflow.di.modules.AppComponent ? in.silentsudo.authflow.di.modules.ActivityModule_BindsAuthActivity.AuthActivitySubcomponent
    2 errors
    

    编辑:

    混凝土等级

    public class AuthPresenterImpl extends AbstractPresenter {
    
        @Inject
        public AuthPresenterImpl(AuthApi api) {
    
        }
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Chetan Sachdeva    8 年前

    这是您的依赖循环:

    @Binds
    @IntoMap
    @PresenterKey(PresenterClass.class)
    abstract PresenterClass bindsAuthPresenterClass(PresenterClass authViewModel);
    

    @Binds
    @IntoMap
    @PresenterKey(ConcretePresenterClass.class)
    abstract PresenterClass bindsAuthPresenterClass(ConcretePresenterClass authViewModel);
    

    参考 Dagger 2 - Why is this a dependency cycle?

        2
  •  -1
  •   silentsudo    8 年前

    我设法解决了这个问题,依赖性问题就在这一行

    @Binds
    abstract PresenterFactory bindsPresenterFactory(PresenterFactory viewModelFactory);
    

    在这里,我需要返回一个引用并提供该引用的具体实现者。 工作变化如下:

    public interface PresenterFactory {
        /**
         * Creates a new instance of the given {@code Class}.
         * <p>
         *
         * @param modelClass a {@code Class} whose instance is requested
         * @param <T>        The type parameter for the ViewModel.
         * @return a newly created ViewModel
         */
        @NonNull
        <T extends PresenterClass> T create(@NonNull Class<T> modelClass);
    }
    

    具体实施者

    @Singleton
    public class PresenterFactoryImpl implements PresenterFactory {
        private final Map<Class<? extends PresenterClass>, Provider<PresenterClass>> creators;
    
        @Inject
        public PresenterFactoryImpl(Map<Class<? extends PresenterClass>, Provider<PresenterClass>> creators) {
            this.creators = creators;
        }
    
        @SuppressWarnings("unchecked")
        @Override
        public <T extends PresenterClass> T create(Class<T> modelClass) {
            Provider<? extends PresenterClass> creator = creators.get(modelClass);
            if (creator == null) {
                for (Map.Entry<Class<? extends PresenterClass>, Provider<PresenterClass>> 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) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }
    

    PresenterModule

    @Module
    public abstract class PresenterModule {
    
        @Binds
        @IntoMap
        @PresenterKey(AuthPresenterImpl.class)
        abstract PresenterClass bindsAuthPresenterImpl(AuthPresenterImpl authViewModel);
    
        @Binds
        abstract PresenterFactory bindsPresenterFactory(PresenterFactoryImpl viewModelFactory);
    }
    
    推荐文章