如何将 AndroidInjector 与子组件一起使用

How to use AndroidInjector with subcomponents

我想关注

应用组件

假设我有四个活动 A、B、C 和 D

如何让 AndroidInjector 工作,这样我就可以拥有

虽然没有内置的方法来执行此操作,但您可以通过在应用程序中提供 HasActivityInjector 的实现来自行执行此操作。您需要重新创建 dagger.android 为您提供的一些细节,但这并不是那么糟糕。

请参阅 DaggerApplication 的默认实现,DispatchingAndroidInjector,它在其 maybeInject 方法中仅参考多绑定构建 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 的注入器。这意味着您需要使注入器(子组件构建器)作为 "red" 和 "blue" 的 public API 的一部分可访问,并弄清楚这些子组件的生命周期是什么样的像。他们长寿吗?每-Activity?无论哪种方式,这都不是其他开发人员可能期望的生命周期,因此请准备好提供充足的文档。