I probably missed something, but I thought Scopes like @Singleton are used to define "scoped lifecycles".
I use Dagger 2 in an Android app (but I don't think the problem is android related at all).
I have 1 Module:
@Module public class MailModule {
@Singleton @Provides public AccountManager providesAccountManager() {
return new AccountManager();
}
@Singleton @Provides public MailProvider providesMailProvider(AccountManager accountManager) {
return new MailProvider(accountManager);
}
}
I have two different components with @Singleton
scope:
@Singleton
@Component(modules = MailModule.class)
public interface LoginComponent {
public LoginPresenter presenter();
}
@Singleton
@Component(
modules = MailModule.class
)
public interface MenuComponent {
MenuPresenter presenter();
}
Both, MenuPresenter
and LoginPresenter
, have an @Inject
constructor. While MenuPresenter expects MailProvider
as parameter, LoginPresenter takes an AccountManager
:
@Inject public MenuPresenter(MailProvider mailProvider) { ... }
@Inject public LoginPresenter(AccountManager accountManager) { ... }
But every time I use the components to create a MenuPresenter
or LoginPresenter
I get a fresh new instance of MailProvider
and AccountManager
. I thought they were in the same scope and should therefore be kind of singleton (in the same scope).
Did I understand something completely wrong. How do I define a real singleton for multiple components in dagger 2?
I assume that
LoginComponent
andMenuComponent
are used separately, e.g. inLoginActivity
andMenuActivity
. Each component is built inActivity.onCreate
. If so, components are recreated every time new activity created, modules and dependencies too, independent of what scope they bond to. Therefore, you get new instances ofMainProvider
andAccountManager
every time.MenuActivity
andLoginActivity
have separate livecycles, so dependencies fromMailModule
cannot be singleton in both of them. What you need is to declare root component with@Singleton
scope (e.g. in Application subclass), makeMenuComponent
andLoginComponent
depend on it. Activity level component cannot be @Singleton scoped, better to create your own scopes using@Scope
annotation, e.g.:Or you can leave them unscoped.
Regarding scopes at all here's brief from initial Dagger 2 proposal:
From my own practice, it's clearer not to use
@Singleton
at all. Instead of that, I use@ApplicationScope
. It serves to define singletons on whole application and does not have additional restrictions as@Singleton
has.Hope that helps you :). It's quite tricky to be understood quickly, takes time, for me at least it was.
You can do the following to define a real singleton for multiple components. I am assuming
@ApplicationScoped
and@ActivityScoped
to be the different scopes.Then a
MailComponent
can be defined for theMailModule
. TheLoginComponent
andMenuComponent
can depend on theMailComponent
.The
MailComponent
can be initialized as shown below and can be used inMenuComponent
andLoginComponent
again shown below.