Java 匕首2中的瞄准镜
我可能遗漏了什么,但我认为像@Singleton这样的作用域是用来定义“作用域生命周期”的 我在安卓应用程序中使用了Dagger2(但我认为这个问题根本与安卓无关) 我有1个模块: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 @
@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被特别处理,因为它不能有任何作用域依赖项。每个人都希望单身汉成为“根”
@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()