Dagger 2 将子组件添加到父组件

Her*_*s84 5 android dagger-2 subcomponent

嗨,社区,我在理解 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();
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我知道,这个想法是我可以绑定子组件或它们的构建器。第二个问题什么时候绑定构建器,什么时候绑定子组件?例如我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);
Run Code Online (Sandbox Code Playgroud)

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

Jef*_*ica 1

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

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

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

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

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

    @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);
    
    Run Code Online (Sandbox Code Playgroud)

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

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