Dagger 2 向父组件添加子组件

Dagger 2 Adding a subcomponent to a parent component

大家好,我无法理解以新方式添加子组件的 Dagger 2(在 Dagger 2.7 中添加)。请参见下面的示例:

@Component(modules = {AppModule.class, MainActivityBinder.class})
@Singleton
interface AppComponent
{
   inject(MyApplication _)
}

@Subcomponent(modules = ActivityModule.class)
interface ActivitySubcomponent
{
   inject(MainActivity _)

   @Subcomponent.Builder
   interface Builder
   {
      @BindInstance
      Builder activity(Activity activity)

      ActivitySubcomponent build();
   }
}

第一步:我有 AppComponent 我的根组件,提供 AppModule 单例(改造,okhttp 等)在 ActivitySubcomponent 我提供 ActivityModule with 具有指定给 activity 的依赖项。现在必须将子组件添加到 AppComponent,所以我以新的方式创建了名为 MainActivityBinder 的指定模块,它具有注释 @Module.subcomponents 并指向绑定子组件,但我有第一个问题,什么应该在那个绑定模块的主体中​​?

@Module(subcomponents = ActivitySubcomponent.class)
public class MainActivityBinder
{
  //what body of this class should be ??
}

我知道,这个想法是我可以绑定子组件或它们的构建器。第二个问题什么时候绑定生成器,什么时候绑定子组件?例如,我的 ActivitySubcomponent 需要 activity 上下文,所以我创建了为 ActivityModule 提供上下文的构建器,在这种情况下,在 MainActivityBinder 中提供构建器会更好吗?第三个问题如何调用组件构建器以及如何获取应用程序组件的子组件?在标准子组件工厂中,我向 AppComponent 方法添加了 return 子组件并且我可以定义参数(例如给出 activity 上下文,如下所列)

@Component(modules = {AppModule.class})
@Singleton
interface AppComponent
{
   ActivitySubcomponents newActivitySubcomponents(Activity activity);

   inject(MyApplication _);
}

// in MainActivity
appComponent.newActivitySubcomponents(this).build().inject(this);

所以在新的子组件添加方法中实现了这种行为?

  1. 您的模块 MainActivityBinder 允许为空,如果您没有其他任何东西可以与之绑定,则应该为空。当您只使用 Module.includes 时,空(仅注释)模块也很有用,例如当您希望将模块列表保留在一个地方而不是在多个组件之间复制它时。注释上的 subcomponents 属性足以让 Dagger 理解您要执行的操作。

  2. 当且仅当它没有@BindsInstance 方法或可实例化模块(Dagger 无法实例化)时,您可以注入 FooSubcomponent 或 Provider。如果您的所有模块都是接口、抽象 类 或具有 public 零参数构造函数的模块,那么您可以直接注入子组件。否则你应该注入你的子组件构建器。

  3. 您可以通过在 AppComponent 上创建一个 return 方法来访问您的子组件构建器,就像您可以对图中存在的任何绑定一样:

    @Component(modules = {AppModule.class, MainActivityBinder.class})
    @Singleton
    interface AppComponent {
      ActivitySubcomponent.Builder activitySubcomponentBuilder();
    
      inject(MyApplication _)
    }
    

    您也可以将其注入到您选择的对象中。

    @Inject ActivitySubcomponent.Builder activitySubComponentBuilder;
    activitySubComponentBuilder.activity(this).build().inject(this);
    
    // You can also inject a Provider<ActivitySubcomponent.Builder> if you want,
    // which is a good idea if you are injecting this directly into your Application.
    // Your Application will outlive your Activity, and may need to inject several
    // instances of the Activity across application lifetime.
    @Inject Provider<ActivitySubcomponent.Builder> activitySubComponentBuilderProvider;
    activitySubComponentBuilderProvider.get().activity(this).build().inject(this);
    

虽然注入子组件构建器似乎没有太大优势,但您可以轻松地调用组件上的方法(return 构建器或 return 子组件),注入生成器有几个优点:

  • Dagger 无法判断您是否调用了组件上的方法,因此即使您的子组件未被使用,它也会生成并编译代码。 Dagger 可以 判断您是否曾尝试注入构建器,因此如果没有 subcomponent/builder 注入和方法,Dagger 将跳过为子组件生成代码。
  • 如果您的代码库足够大,您必须将其拆分为不同的目标进行编译,工厂方法技术可能会陷入某些依赖循环,您的应用程序的组件和模块依赖于一切,您只能获得从您的组件本身到您的子组件。使用可注入的子组件构建器,您有更多关于如何获取子组件或构建器的选项。