Dagger 2:定义子组件

时间:2017-04-04 18:32:22

标签: android dagger-2

我按照此guide为我的Android应用程序制作子组件。在这里,我定义了一个名为LoginComponent的子组件,用于LoginActivity:

@Subcomponent(modules = LoginModule.class)
public interface LoginComponent {

    void inject(LoginActivity activity);

    @Subcomponent.Builder
    interface Builder {
        Builder requestModule(LoginModule module);
        LoginComponent build();
    }
}


@Module
public class LoginModule {
    @Provides
    LoginManager provideLoginManager(LoginManagerImpl manager) {
        return manager;
    }

    @Provides
    LoginView provideLoginView(LoginViewImpl view) {
        return view;
    }

    @Provides
    LoginPresenter loginPresenter(LoginView view, LoginManager manager) {
        return new LoginPresenterImpl(view, manager);
    }
}

我在另一个组件中定义了这个子组件:

@Module(subcomponents = LoginComponent.class)
public interface AppModule {
}

@Singleton
@Component(modules = {
        AppModule.class
})
public interface AppComponent {
}

这是我的LoginActivity:

public class LoginActivity extends AppCompatActivity  {

    @Inject LoginPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
    }
}

我的问题是:

  1. @Subcomponent.Builder的目的。我不明白这一点,因为此组件中的所有模块都已在@Subcomponent注释中定义。我们为什么要重复一次。
  2. 如何在上述活动中注入LoginPresenter。
  3. 由于

1 个答案:

答案 0 :(得分:3)

  1. @Subcomponent.Builder遵循@Component.Builder中记录的相同规则:您需要为Dagger无法初始化的每个模块设置一个setter。 (允许模块具有构造函数参数或静态工厂方法,这会阻止Dagger创建自己的实例。)

    因为Dagger可以通过调用零参数构造函数来创建一个LoginModule,所以可以从Builder中删除该方法;你不需要重新创建它。您也可以考虑使用LoginModule的方法static,这将允许您使LoginModule成为接口或抽象类 - 然后Dagger将能够避免持有对模块的引用。最后,对于绑定两个类的简单@Provides方法(例如@Provides B provideB(A a) { return a; }),您可以切换到@Binds,这样可以使生成的代码更快。

    此时,您的@Subcomponent.Builder成为特定于子组件的Provider:您可以注入BuilderProvider<Builder>并通过调用{{{{}}来获取新的子组件实例1}}就可以了。只要您不需要提供任何模块实例,您就不需要在构建器上使用任何其他方法。

    你可以简单地注射一个build(),但我在实践中没有看到它,并且我自己没有尝试过。

  2. 要注入LoginPresenter,您需要访问AppComponent,创建一个新的LoginComponent,并通过传入它来使用它注入您的Activity。但是,这可能很难,因为您还没有给自己任何注入LoginComponent.Builder的权限。

    除非您想尝试使用dagger.android,否则可以添加一个方法来调用AppComponent来创建新的LoginComponent。

    Provider<LoginComponent>

    有时您会看到名为// This way... LoginComponent createLoginComponent(); // or this way: LoginComponent.Builder createLoginComponentBuilder(); 的第一种方式,这是在Dagger 1中建立的命名约定;第一种方法还可以避免创建@ Subcomponent.Builder或在plus()中添加子组件,尽管您可能希望以您拥有它的方式保留结构,以便稍后可以向AppModule添加更多。

    要完成它,在AppModule中,您可以让您的活动获取您的应用程序,访问其AppComponent并注入自己。

    Activity.onCreate