Java 匕首2中的瞄准镜

Java 匕首2中的瞄准镜,java,android,dagger-2,Java,Android,Dagger 2,我可能遗漏了什么,但我认为像@Singleton这样的作用域是用来定义“作用域生命周期”的 我在安卓应用程序中使用了Dagger2(但我认为这个问题根本与安卓无关) 我有1个模块: @Module public class MailModule { @Singleton @Provides public AccountManager providesAccountManager() { return new AccountManager(); } @Singleton @

我可能遗漏了什么,但我认为像@Singleton这样的作用域是用来定义“作用域生命周期”的

我在安卓应用程序中使用了Dagger2(但我认为这个问题根本与安卓无关)

我有1个模块:

@Module public class MailModule {

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

  @Singleton @Provides public MailProvider providesMailProvider(AccountManager accountManager) {
    return new MailProvider(accountManager);
  }
}
我有两个具有
@Singleton
作用域的不同组件:

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

  public LoginPresenter presenter();
}


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

  MenuPresenter presenter();

}
MenuPresenter
LoginPresenter
都有一个
@Inject
构造函数。MenuPresenter需要
邮件提供程序
作为参数,而LoginPresenter需要
帐户管理器

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

  @Inject public LoginPresenter(AccountManager accountManager) { ... }
但是每次我使用这些组件创建
MenuPresenter
LoginPresenter
时,我都会得到一个新的
MailProvider
AccountManager
实例。我认为它们在同一范围内,因此应该是某种单例(在同一范围内)


我是不是完全错了。如何为dagger 2中的多个组件定义一个真正的单例

我假设
LoginComponent
MenuComponent
是分开使用的,例如在
LoginActivity
MenuActivity
中。每个组件都内置于
活动中。onCreate
。如果是这样,那么每次创建新活动时都会重新创建组件,模块和依赖项也会重新创建,而与它们绑定到的范围无关。因此,每次都会得到
MainProvider
AccountManager
的新实例

MenuActivity
LoginActivity
具有单独的活动周期,因此来自
MailModule
的依赖项不能在这两种活动中都是单一的。您需要的是使用
@Singleton
范围声明根组件(例如在应用程序子类中),使
MenuComponent
LoginComponent
依赖于它。活动级别组件不能@Singleton Scope,最好使用
@Scope
注释创建自己的作用域,例如:

@Retention(RetentionPolicy.RUNTIME)
@Scope
public @interface MenuScope {
}
或者你可以让他们不受影响

关于所有的范围,以下是开头的简要说明:

该声明使dagger能够强制执行以下约束:

  • 给定的组件只能具有未作用域或已声明作用域的绑定(包括类上的作用域注释)。 也就是说,一个组件不能代表两个作用域。当没有范围时 已列出,绑定只能是无范围的
  • 作用域组件只能有一个作用域依赖项。这是一种机制,强制两个组件不各自声明它们的 自己的作用域绑定。例如,两个单件组件,每个组件具有 他们自己的@Singleton缓存将被破坏
  • 组件的作用域不得出现在其任何可传递依赖项中。例如:SessionScoped->RequestScoped->SessionScoped 没有任何意义,是一个bug
  • @Singleton被特别处理,因为它不能有任何作用域依赖项。每个人都希望单身汉成为“根”
这种规则组合的目标是在范围为 应用时,组件的组成结构与我们使用的相同 使用Dagger 1.0 plus()'d对象图,但能够 了解所有绑定及其作用域的静态知识。放置 另一种方式是,当应用范围时,这限制了图形的范围 只能构建到那些可以正确构建的对象

从我自己的实践来看,完全不使用
@Singleton
更清楚。相反,我使用了
@ApplicationScope
。它用于在整个应用程序上定义单例,并且没有像
@Singleton
那样的附加限制


希望对您有所帮助:)。很难快速理解,需要时间,至少对我来说是这样。

您可以执行以下操作为多个组件定义一个真正的单例。我假设
@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);
  }
}
然后可以为
MailModule
定义
MailComponent
LoginComponent
MenuComponent
可以依赖于
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();
}
MailComponent
可以如下所示进行初始化,并且可以在下面再次显示的
MenuComponent
LoginComponent
中使用

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

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

DaggerLoginComponent.builder().mailComponent(mailComponent).build()            

但是一个组件只能有一个范围注释,对吗?如果我有一个具有
@application
的应用程序组件和具有
@Activity
作用域的LoginComponent,我该如何做呢?对。组件不能用两个作用域进行注释。如果在注释
@component(dependencies=ApplicationComponent.class)
中定义了活动范围组件,则它将具有来自应用程序范围组件的所有依赖项。将具有作用域的组件视为图和子图。应用程序组件及其作用域根图、活动组件及其作用域根子图。避免使用
@Singleton
作用域是否允许将
@Application
依赖项注入
@activity
作用域?例如,如果MyPresenter属于
@Application
范围,我想将其注入到属于
@Activity
范围的MyActivity中。@AAverin确实如此。但我认为也可以通过使用
@Singleton
来实现。这是迄今为止我找到的最好的解释+1将
@ApplicationScoped
分别写在模块的每个方法上与将其写在@Module上一次有什么区别吗?@JemshitIskenderov-将
@ApplicationScoped
注释放在
@Module
上不会有任何效果。模块的目的是通过提供程序方法(用
@注释的方法提供
注释)提供依赖关系。这些提供程序方法可能有作用域,也可能没有作用域。因此,在提供者方法级别定义作用域变得非常重要。
MailComponent mailComponent = DaggerMailComponent.builder().build();

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

DaggerLoginComponent.builder().mailComponent(mailComponent).build()