匕首的范围2

soc*_*qwe 26 java android dagger-2

我可能错过了一些东西,但我认为像@Singleton这样的Scopes用来定义"范围生命周期".

我在Android应用程序中使用Dagger 2(但我不认为这个问题与Android有关).

我有1个模块:

@Module public class MailModule {

  @Singleton @Provides public AccountManager providesAccountManager() {
    return new AccountManager();
  }

  @Singleton @Provides public MailProvider providesMailProvider(AccountManager accountManager) {
    return new MailProvider(accountManager);
  }
}
Run Code Online (Sandbox Code Playgroud)

我有两个不同的组件,@Singleton范围:

@Singleton
@Component(modules = MailModule.class)
public interface LoginComponent {

  public LoginPresenter presenter();
}


@Singleton
@Component(
    modules = MailModule.class
)
public interface MenuComponent {

  MenuPresenter presenter();

}
Run Code Online (Sandbox Code Playgroud)

两者都有,MenuPresenter并且LoginPresenter有一个@Inject构造函数.虽然MenuPresenter期望MailProvider作为参数,但LoginPresenter需要AccountManager:

  @Inject public MenuPresenter(MailProvider mailProvider) { ... }

  @Inject public LoginPresenter(AccountManager accountManager) { ... }
Run Code Online (Sandbox Code Playgroud)

但每次我使用组件创建一个MenuPresenterLoginPresenter我得到一个新的MailProvider和新的实例AccountManager.我认为它们属于同一范围,因此应该是单一的(在同一范围内).

我是否完全理解了一些错误.如何在匕首2中为多个组件定义真正的单例?

Kir*_*nov 51

我假设LoginComponent并且MenuComponent单独使用,例如在LoginActivity和中MenuActivity.每个组件都是内置的Activity.onCreate.如果是这样,每次创建新活动时,都会重新创建组件,模块和依赖项,而与它们所绑定的范围无关.因此,你得到的新情况MainProviderAccountManager每一次.

MenuActivity并且LoginActivity具有单独的livecycles,因此依赖关系MailModule不能在它们中都是单例.你需要的是用@Singleton范围声明根组件(例如在Application子类中),make MenuComponentLoginComponent依赖它.活动级别组件不能是@Singleton作用域,更好的是使用@Scope注释创建自己的作用域,例如:

@Retention(RetentionPolicy.RUNTIME)
@Scope
public @interface MenuScope {
}
Run Code Online (Sandbox Code Playgroud)

或者你可以让他们不受约束.

关于范围,根据最初的Dagger 2提案的简要说明:

@Singleton
@Component(modules = {…})
public interface ApplicationComponent {}
Run Code Online (Sandbox Code Playgroud)

该声明使匕首能够执行以下约束:

  • 给定组件可能只有未绑定或声明范围的绑定(包括类的范围注释).即组件不能代表两个范围.如果未列出范围,则绑定可能仅为未范围.
  • 范围组件可能只有一个范围依赖项.这是一种机制,强制两个组件不会各自声明自己的作用域绑定.例如,每个拥有自己的@Singleton Cache的两个Singleton组件都将被破坏.
  • 组件的范围不得出现在其任何传递依赖项中.例如:SessionScoped - > RequestScoped - > SessionScoped没有任何意义,是一个错误.
  • @Singleton的特殊处理方式是它不能有任何作用域依赖项.每个人都希望Singleton成为"根".

这种规则组合的目标是强制执行范围应用时,组件使用与Dagger 1.0 plus()'d ObjectGraphs相同的结构,但能够具有所有的静态知识.绑定及其范围.换句话说,当应用范围时,这限制了图形,而不是仅构建可以正确构造的图形.

从我自己的实践来看,根本不使用它更清楚@Singleton.而不是那样,我用@ApplicationScope.它用于在整个应用程序中定义单例,并且没有其他限制@Singleton.

希望能帮到你:).快速理解是非常棘手的,需要时间,至少对我而言.

  • 对。组件不能使用两个范围进行注释。如果在注解@Component(dependencies = ApplicationComponent.class)中定义了活动范围组件,则该活动范围组件将具有来自应用程序范围组件的所有依赖关系。将具有范围的组件视为图和子图。应用程序组件及其范围-根图,活动组件及其范围-根的子图。 (2认同)

Pra*_*pta 7

您可以执行以下操作来为多个组件定义实际单例.我假设@ApplicationScoped并且@ActivityScoped是不同的范围.

@Module public class MailModule {
  @Provides @ApplicationScoped 
  public AccountManager providesAccountManager() {
    return new AccountManager();
  }

  @Provides @ApplicationScoped
  public MailProvider providesMailProvider(AccountManager accountManager) {
        return new MailProvider(accountManager);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后MailComponent可以定义一个MailModule.该LoginComponentMenuComponent可以依靠的MailComponent.

@ApplicationScoped
@Component(modules = MailModule.class)
public interface MailComponent {
  MailProvider mailProvider();
  AccountManager accountManager();
}

@ActivityScoped
@Component(dependencies = MailComponent.class)
public interface LoginComponent {
  LoginPresenter presenter();
}

@ActivityScoped
@Component(dependencies = MailComponent.class)
public interface MenuComponent {
  MenuPresenter presenter();
}
Run Code Online (Sandbox Code Playgroud)

MailComponent如下图所示,可以用在可被初始化MenuComponentLoginComponent下面再次示出.

MailComponent mailComponent = DaggerMailComponent.builder().build();

DaggerMenuComponent.builder().mailComponent(mailComponent).build();

DaggerLoginComponent.builder().mailComponent(mailComponent).build()            
Run Code Online (Sandbox Code Playgroud)

  • @JemshitIskenderov - 将`@ApplicationScoped`注释放在`@ Module`顶部将无效.模块的目的是通过提供程序方法(使用`@ Provide`注释注释的方法)提供依赖关系.这些提供者方法可能有也可能没有范围.因此,在提供者方法级别定义范围变得很重要. (2认同)