Using Dagger2 DispatchingAndroidInjector in multi module project

Viewed 321

I've an issue when using Dagger in multi module project. Let's say we have three modules.

  • core
  • newfeaturesmodule -> api project(":core")
  • oldfeaturesmodule -> api project(":newfeaturesmodule")

Application classes has same hierarchy either. The problem was both newfeaturesmodule and oldfeaturesmodule are using AndroidInjector method to inject activites. And it ended up with a crash saying activities on newfeaturesmodule has no android injector factory. The problem was when i call first application inject in newfeaturesmodule everything was just fine. And then child oncreate method of application class on oldfeaturesmodule called and it called inject for application again but these time it replaced the activity injectors on oldfeaturemodule with activity injectors on newfeaturemodule. So i came up with a custom solution like this

public abstract class CoreApp extends Application {

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

        CoreComponent component =
                DaggerCoreComponent.builder().coreModule(new CoreModule()).build();

        initDependencies(component);
    }

    public abstract void initDependencies(CoreComponent component);
}
public abstract class NewFeaturesApp extends CoreApp implements HasActivityInjector {

    public NewFeaturesComponent newFeaturesComponent;

    @Inject Map<Class<?>, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithClassKeys;

    @Inject Map<String, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithStringKeys;

    @Override
    public void initDependencies(CoreComponent component) {
        newFeaturesComponent = DaggerNewFeaturesComponent.builder().coreComponent(component).build();
        newFeaturesComponent.inject(this);
        keepAndroidInjectors(injectorFactoriesWithClassKeys, injectorFactoriesWithStringKeys);
        initLegacyDependencies(newFeaturesComponent);
    }

    public abstract void keepAndroidInjectors(
            Map<Class<?>, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithClassKeys,
            Map<String, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithStringKeys);

    public abstract void initLegacyDependencies(NewFeaturesComponent component);
}
public class OldFeaturesApp extends NewFeaturesApp {

    public OldFeaturesComponent oldFeaturesComponent;

    DispatchingAndroidInjector<Object> dispatchingAndroidInjector;

    @Inject Map<Class<?>, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithClassKeys;

    @Inject Map<String, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithStringKeys;

    Map<Class<?>, Provider<AndroidInjector.Factory<?>>> newInjectorFactoriesWithClassKeys;

    Map<String, Provider<AndroidInjector.Factory<?>>> newInjectorFactoriesWithStringKeys;

    @Override
    public void keepAndroidInjectors(
            Map<Class<?>, Provider<AndroidInjector.Factory<?>>> newInjectorFactoriesWithClassKeys,
            Map<String, Provider<AndroidInjector.Factory<?>>> newInjectorFactoriesWithStringKeys) {
        this.newInjectorFactoriesWithClassKeys = newInjectorFactoriesWithClassKeys;
        this.newInjectorFactoriesWithStringKeys = newInjectorFactoriesWithStringKeys;
    }

    @Override
    public void initLegacyDependencies(OldFeaturesComponent component) {
        oldFeaturesComponent = DaggerOldFeaturesComponent.builder()
                .application(this)
                .dependent(component)
                .build()
                .inject(this);

        Map<Class<?>, Provider<AndroidInjector.Factory<?>>> mergedInjectorFactoriesWithClassKeys = new HashMap<>();
        Map<String, Provider<AndroidInjector.Factory<?>>> mergedInjectorFactoriesWithStringKeys = new HashMap<>();

        mergedInjectorFactoriesWithClassKeys.putAll(newInjectorFactoriesWithClassKeys);
        mergedInjectorFactoriesWithClassKeys.putAll(injectorFactoriesWithClassKeys);

        mergedInjectorFactoriesWithStringKeys.putAll(newInjectorFactoriesWithStringKeys);
        mergedInjectorFactoriesWithStringKeys.putAll(injectorFactoriesWithStringKeys);

        dispatchingAndroidInjector = DispatchingAndroidInjector_Factory.newInstance(
                mergedInjectorFactoriesWithClassKeys, mergedInjectorFactoriesWithStringKeys);
    }

    public AndroidInjector<Object> androidInjector() {
        return dispatchingAndroidInjector;
    }
}

So i have two questions

  • Are there any way to merge activityInjectorFactories in Dagger?

  • And second, is my approach fine for this case or has it some downsides ? Could that be improved with providing these map dependencies from my NewFeaturesModule maybe, or something else ?

(Note: Dagger version is 2.27)

0 Answers
Related