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

raf*_*kob 7 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(){
         ...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

活动:

public class LoginActivity {
    @Inject LoginPresenter mPresenter;
}
Run Code Online (Sandbox Code Playgroud)

主持人:

public class LoginPresenter {

    @Inject
    public LoginPresenter(Retrofit retrofit) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

raf*_*kob 6

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

1)LoginPresenter注入LoginActivity

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

我尝试将演示者注入到两个变量中:

public class LoginActivity {
    @Inject LoginPresenter A;
    @Inject LoginPresenter B;
}
Run Code Online (Sandbox Code Playgroud)

LoginPresenter注释为:

  • 没什么-A并且B不同
  • @PerActivity -AB是相同的
  • @PerApp -AB是相同的

2)LoginPresenter注入LoginActivityMainActivity:

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

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

public class LoginActivity {
    @Inject LoginPresenter A;
}

public class MainActivity {
    @Inject LoginPresenter B;
}
Run Code Online (Sandbox Code Playgroud)

LoginPresenter注释为:

  • 没什么-A并且B不同
  • @PerActivity -AB是不同的
  • @PerApp -AB是相同的


Bar*_*ski 3

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

我们假设:

  1. 这是您用来将内容注入到您的LoginActivity

@PerActivity
@Component(dependencies = ApplicationComponent.class, modules = LoginActivityModule.class)
public interface LoginActivityComponent {
    void inject(LoginActivity loginActivity);
}
Run Code Online (Sandbox Code Playgroud)
  1. 您使用 anApplicationComponent来提供@PerApp范围内的对象

如果您没有指定特定对象module应提供特定对象的方式(LoginPresenter例如),那么您基本上是在对您说component

我需要一个LoginPresenter实例。我不在乎谁创造了它。你自己弄清楚吧。

该组件检查是否有任何依赖components/modules知道如何创建它。如果没有,则被请求者component需要自己创建它(在依赖的匕首元素的帮助下)。

注入component只能尝试引用(“创建”)来自同一范围的对象。因此,如果LoginActivityComponentfrom @PerActivity,它只能创建来自此范围的对象。

如果您未在 中指定范围LoginPresenter,则 dagger 将假定与注入组件具有相同的范围。如果您明确指定@PerActivity范围,它将与component范围匹配并且一切都会正常。但是,如果您指定不同的范围(例如@PerApp),您的应用程序将无法正确构建,因为没有任何类@PerApp提供创建LoginPresenter.

免责声明:我的解释中可能有一些部分被简化了,因此更容易理解(主要是在谁具体做了什么方面)。我尽量不做任何与 Dagger2 本身逻辑相矛盾的简化。