Dagger 2 - 构造函数注入 - 范围

时间:2016-04-06 09:41:13

标签: java android dagger-2

我正在使用具有简单MVP模式的Dagger 2。我有一个@PerApp@PerActivity范围。我正在使用构造函数注入注入演示者依赖项,这使得这些演示者“可注入”(我不需要在活动模块中编写提供方法)。代码片段:

PerApp:

// AppComponent
@PerApp
@Component(modules = {AppModule.class, DataModule.class, NetworkModule.class})
public interface AppComponent {
    LoginComponent plus(LoginModule loginModule);

    MainComponent plus(MainModule mainModule);
}

// Example @PerApp module
@Module
public class NetworkModule {

    @Provides
    @PerApp
    Retrofit providesRetrofit(){
         ...
    }
}

PerActivity:

// LoginModule
@Module
public class LoginModule {
    private final LoginActivity mLoginActivity;

    public LoginModule(LoginActivity loginActivity) {
        mLoginActivity = loginActivity;
    }

    @Provides
    @PerActivity
    Context providesContext() {
        return mLoginActivity;
    }
}

// LoginComponent
@PerActivity
@Subcomponent(
        modules = LoginModule.class
)
public interface LoginComponent {
    void inject(LoginActivity loginActivity);
}

的活动:

public class LoginActivity {
    @Inject LoginPresenter mPresenter;
}

主讲人:

public class LoginPresenter {

    @Inject
    public LoginPresenter(Retrofit retrofit) {
        ...
    }
}

它运作良好。我的问题是:提供LoginPresenter的范围是什么?它会跟LoginActivity一样吗?我应该用@PerActivity或其他东西注释演示者的构造函数吗?

3 个答案:

答案 0 :(得分:3)

这完全取决于您用于注射的组件。

让我们假设:

  1. 这是您用于将内容注入LoginActivity的组件:
  2. @PerActivity
    @Component(dependencies = ApplicationComponent.class, modules = LoginActivityModule.class)
    public interface LoginActivityComponent {
        void inject(LoginActivity loginActivity);
    }
    
    1. 您使用ApplicationComponent来提供@PerApp范围内的对象
    2. 如果您没有指定特定module应该提供特定对象的方式(例如LoginPresenter),那么您基本上是对component说:

        

      我需要一个LoginPresenter个实例。我不在乎谁创造了那个。只是弄清楚自己。

      此组件检查是否有任何从属components / modules知道如何创建它。如果没有,被询问的component需要自己创建(在相关的匕首元素的帮助下)。

      注入component只能尝试引用来自同一范围的对象("创建")。因此,如果LoginActivityComponent来自@PerActivity,则它可以创建仅来自此范围的对象。

      如果您未在LoginPresenter中指定范围,则匕首将采用与注射组件相同的范围。如果明确指定@PerActivity范围,它将匹配component范围,一切都会正常。但是,如果您指定了不同的范围(例如@PerApp),则您的应用无法正确构建,因为@PerApp中没有任何类提供创建LoginPresenter的方式。

      Disclamer:我的解释可能很少有部分我已经简化了,所以它更容易理解(主要是关于谁做了什么)。我尽量不做任何与Dagger2本身的逻辑相矛盾的简化。

答案 1 :(得分:3)

我已经运行了一些测试来自行检查确定范围如何与构造函数注入一起工作,这是我的结果。

1)将LoginPresenter注入LoginActivity

LoginComponent - @PerActivity范围(代码与我的第一篇文章完全相同)

我试图将演示者注入2个变量:

public class LoginActivity {
    @Inject LoginPresenter A;
    @Inject LoginPresenter B;
}

LoginPresenter注明:

  • 没有 - AB不同
  • @PerActivity - AB相同
  • @PerApp - AB相同

2)将LoginPresenter注入LoginActivityMainActivity

LoginComponentMainComponent - @PerActivity范围(代码与我的第一篇文章完全相同)

我试图将演示者注入两个不同的活动:

public class LoginActivity {
    @Inject LoginPresenter A;
}

public class MainActivity {
    @Inject LoginPresenter B;
}

LoginPresenter注明:

  • 没有 - AB不同
  • @PerActivity - AB不同
  • @PerApp - AB相同

答案 2 :(得分:2)

在具有带有@Inject批注的构造函数时,指定范围的方法似乎是使用范围来注释

@PerActivity
public class LoginPresenter {

    @Inject
    public LoginPresenter(Retrofit retrofit) {
        ...
    }
}

我假设LoginPresenter仅在LoginActivity中注入,这意味着 Dagger 将仅提供一次并创建一个实例。如果您多次注入它,而没有范围注释,您将获得不同的实例。