我想关注
ApplicationComponent
subcomponentBlue(modules = ModuleX.class)
subcomponentRed(modules = ModuleY.class)
让我们说我有四个活动A,B,C和D
如何使AndroidInjector正常工作,我可以
A,B有自己的子组件,它们是subcomponentBlue和
C,D有自己的子组件,是subcomponentRed的子组件
答案 0 :(得分:4)
虽然没有内置方法可以执行此操作,但您可以通过在应用程序中提供HasActivityInjector的实现来自行完成此操作。你需要重新创建一些dagger.android为你提供的细节,但这并不是那么糟糕。
请参阅DaggerApplication的默认实现DispatchingAndroidInjector,它在maybeInject
方法中只是参考multibinding-built Map<Class, AndroidInjector.Factory>
来生成AndroidInjector并调用inject
。如果你正在关注dagger.android用户指南,那么每个AndroidInjector都会成为一个子组件,并且每个AndroidInjector.Factory都恰好是使用@ContributesAndroidInjector安装的子组件构建器,但这些不是要求。
相反,您的应用程序将包含看起来像这样的代码:
public class YourApplication extends Application implements HasActivityInjector {
// Let's assume your application component calls inject(this) so these
// @Inject fields are populated, and that you've instantiated some subcomponents
// that are long-lived. Of course, you can inject your Subcomponent.Builder
// interfaces instead, if you want a new subcomponent per activity.
@Inject SubcomponentBlue subcomponentBlue;
@Inject SubcomponentRed subcomponentRed;
@Override public AndroidInjector<Activity> activityInjector() {
// If you can use Java 8 syntax from Android, a lambda would work
// nicely here, as in "return activity -> { ... };".
return new AndroidInjector<Activity>() {
@Override public void inject(Activity activity) {
if (activity instanceof ActivityA) {
// HERE'S THE MAGIC: We know that activity is an ActivityA,
// and that subcomponentBlue has an ActivityA injector, so we
// perform a cast and then use the Builder to create an
// injector that we inject with.
ActivityA aActivity = (ActivityA) activity;
subcomponentBlue.aInjectorBuilder().create(aActivity).inject(aActivity);
} elseif (activity instanceof ActivityB) { // ...
} elseif (activity instanceof ActivityC) {
ActivityC cActivity = (ActivityC) activity;
subcomponentRed.cInjectorBuilder().create(cActivity).inject(cActivity);
} elseif (activity instanceof ActivityD) { // ...
} else {
Exception aTantrum = new IllegalArgumentException("Injector not found");
throw aTantrum;
}
}
};
}
}
以上是有效的,但非常冗长。作为替代方案,您可以手动将活动绑定到多绑定地图,而不是使用@ContributesAndroidInjector
,而是通过子组件访问它们:
@Module public class YourApplicationModule {
@Provides @IntoMap @ActivityKey(ActivityA.class)
static AndroidInjector.Factory<Activity> provideAInjector(
SubcomponentBlue subcomponentBlue) {
// Of course, you can also inject a SubcomponentBlue.Builder and
// create a new one each time.
return subcomponentBlue.aInjectorBuilder();
}
// Same for B, C, and D.
}
必备注意事项:在所有这些情况下,您试图在其父子组件“red”和“blue”之外访问A,B,C和D的注入器。这意味着您需要将注入器(子组件构建器)作为“红色”和“蓝色”的公共API的一部分进行访问,并找出这些子组件的生命周期的样子。他们是长寿吗?每个活动?无论哪种方式,这都不是其他开发人员可能期望的生命周期,因此请准备好提供充足的文档。