Dagger 2 Singleton和Activity级别的依赖关系

时间:2018-07-17 12:48:00

标签: java android dagger

我面临的问题是有关在单个Activity中使用App级别和Activity级别的依赖关系。 假设我具有APP级别的依赖项:

 @Module
public class FormatModule {
@Provides
@Singleton
public DecimalFormat getDecimalFormat(){
    DecimalFormat df = new DecimalFormat("0,000.00");
    return df;
}




public class App extends Application {

private static AppComponent AppComponent;

public static AppComponent getAppComponent() {
    return AppComponent;
}

    @Override
    public void onCreate () {
        super.onCreate();

        AppComponent = DaggerAppComponent
                .builder()
                .apiModule(new ApiModule())
                .build();

    }

}

,组件标有@Singleton。

存在活动级别依赖性:

@Module
public class MainActivityModule {

@Provides
Presenter getPresenter(){
    return new Presenter();
}


@Component(modules = {MainActivityModule.class)
public interface MainActivityComponent {
void inject(MainActivity mainActivity);
}

在MainActivity中,我使用以下代码初始化组件:

 MainActivityComponent mainActivityComponent = 
 DaggerMainActivityComponent.builder()
            .mainActivityModule(new MainActivityModule())
            .contextModule(new ContextModule(this))
            .build();
    mainActivityComponent.inject(this);

以及在使用ony应用程序级别依赖项的类中:

App.getAppComponent().inject(this);

问题是如何在MainActivity中同时使用App和Activity级别的依赖关系?

1 个答案:

答案 0 :(得分:0)

要执行此操作,您需要在MainActivityComponent和AppComponent之间建立一个component dependency

@Component(
    modules = {MainActivityModule.class},
    dependencies = {AppComponent.class})      // <-- this
public interface MainActivityComponent {
  void inject(MainActivity mainActivity);
}

这告诉Dagger,它可以在AppComponent上调用零参数方法来提供MainActivityComponent所需的依赖关系,包括MainActivity注入的对象的依赖关系。这使得它特别适合依赖于其他Dagger组件,因为您可以将这些零参数方法添加到AppComponent上,并且Dagger将提供实现。但是,为了清楚起见或避免依赖周期,您可能还选择列出 interface 作为依赖项,然后提供DaggerAppComponent实现。

您需要提供AppComponent的实现作为ActivityComponent构建器的一部分:

MainActivityComponent mainActivityComponent = 
    DaggerMainActivityComponent.builder()
        .mainActivityModule(new MainActivityModule())
        .contextModule(new ContextModule(this))
        .appComponent(App.getAppComponent())           // <-- this
        .build();
mainActivityComponent.inject(this);

重要:在MainActivityComponent中,您唯一可用的绑定是在您列出为依赖项的接口或类上作为零参数方法公开的绑定 (“设置方法”)。如果您在AppComponent模块上使用@Provides方法提供绑定,除非您在AppComponent本身上为其添加了一个吸气剂,否则它将不会出现在MainActivityComponent 中。这使您可以具体说明从AppComponent继承的内容,但可以视为维护负担。

@Component(modules = ModuleA.class) public interface ComponentA {
  BindingOne bindingOne();
}

@Module public abstract class ModuleA {
  @Provides static BindingOne getBindingOne() { return BindingOne.INSTANCE; }
  @Provides static BindingTwo getBindingTwo() { return BindingTwo.INSTANCE; }
}

// ComponentB has access to BindingOne but not BindingTwo, because it can only see
// what is available in ComponentA, not ComponentA's module set that includes ModuleA.
@Component(dependencies = ComponentA.class) public interface ComponentB { /* ... *}

旁注

  1. 如果MainActivityModule具有默认构造函数或其他公共无参数构造函数,则无需在构建器中提供它。匕首会为您创建一个。
  2. getDecimalFormatgetPresenter不使用任何实例状态,因此可以将它们设置为static; Dagger将检测到此情况并进行静态调用,而不是slightly slower on Android的虚拟方法调用。如果将所有@Module方法切换为static @Providesabstract @Binds方法,则可以将Module更改为接口或抽象类,这意味着Dagger可以并且将完全跳过实例化该方法。 / li>
  3. 您需要列出想要在MainActivityComponent上来自AppComponent的所有绑定,因为Dagger可以分别为AppComponent和MainActivityComponent生成代码。作为组件依赖关系的替代方法,您可以选择使用subcomponents,其中Dagger为MainActivityComponent生成代码作为AppComponent的实现细节,您可以从AppComponent获得构建器,而不是DaggerMainActivityComponent上的静态方法。这样可以在MainActivityComponent和AppComponent之间建立更紧密的耦合,但是由于Dagger可以在编译时检查MainActivityComponent的需求并私下提供这些绑定,因此您可以跳过在AppComponent上定义零参数方法。
  4. 用于Android应用程序/活动/片段注入的子组件层次结构的现有框架是dagger.android,该框架可自动为每个Android创建的对象(包括BroadcastReceiver,ContentProvider)创建和安装子组件。和服务。随着您逐渐熟悉Dagger架构,可能需要考虑一下。