5

嗨社区我在理解 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的依赖项中指定了该活动。现在必须将子组件添加到AppComponent,因此我以新的方式创建了名为 的指定模块MainActivityBinder,该模块具有注释 @Module.subcomponents 并指向绑定子组件,但我有第一个问题,该绑定模块的主体应该是什么?

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

我知道,这个想法是我可以绑定子组件或其构建器。第二个问题何时绑定构建器,何时绑定子组件?例如我ActivitySubcomponent需要的活动上下文,所以我创建提供上下文的构建器ActivityModule在这种情况下会更好地在MainActivityBinder构建器中提供?第三个问题如何调用组件构建器以及如何获取应用组件的子组件?在标准子组件工厂中,我添加到AppComponent返回子组件的方法中,我可以定义参数(例如给出活动上下文,如下所列)

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

   inject(MyApplication _);
}

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

那么在新的子组件添加方法中实现了这种行为吗?

4

1 回答 1

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

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

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

    @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);
    

尽管当您可以轻松地调用组件上的方法(返回 Builder 或返回子组件)时,注入子组件构建器似乎没有太多优势,但注入构建器有几个优点:

  • Dagger 无法判断您是否调用了组件上的方法,因此即使您的子组件没有被使用,它也会生成并编译代码。Dagger可以判断您是否曾经尝试注入构建器,因此如果没有子组件/构建器注入且没有方法,Dagger 将跳过为子组件生成代码。
  • 如果您的代码库足够大以至于您必须将其拆分为不同的目标进行编译,工厂方法技术可能会在某些依赖周期中抓住您,在这些依赖周期中,您的应用程序的组件和模块依赖于所有内容,您只能从您的组件本身。使用可注入的子组件构建器,您有更多关于如何访问子组件或构建器的选项。
于 2018-06-29T21:39:24.667 回答