Using Dagger 2.11, the following code returns "Error:[dagger.android.AndroidInjector.inject(T)] Found a dependency cycle:". This is happening because the provideApp method has the argument "App app". If I remove it and do a dirty hack that provides the application instance directly, the code compiles and works.
From examples I've seen before, it used to be common practice to keep an instance of the application in the module and using that for other providers, but since this module class is now abstract, this doesn't work as the @Provide methods need to be static.
How can I solve this?
@Module(includes = AndroidInjectionModule.class)
public abstract class AppModule {
@Provides
@Singleton
static App provideApp(App app) {
return app;
}
@Provides
static Authenticator provideAuthenticator(App app) {
return new AuthenticatorImpl(app);
}
}
EDIT:
What I need to achieve is basically this behaviour:
@Module(includes = AndroidInjectionModule.class)
public class AppModule {
private App application;
AppModule(App app) {
application = app;
}
@Provides
Authenticator provideAuthenticator() {
return new AuthenticatorImpl(application);
}
}
However, this doesn't work since the AppModule is now an abstract class and the app wouldn't compile if I use @Provides Authenticator provideAuthenticator() without the static keyword. If I use the static keyword, then I can't access the non-static application field.
Your code:
@Provides
@Singleton
static App provideApp(App app) {
return app;
}
means "provide App using App as a dependency". In other words, you want to provide App
but you need App
first. Hence your cycle.
The best solution to this problem is to follow the Rule of Demeter and not to provide the Application
singleton at all.
Why does your AuthenticatorImpl
need to know the concrete type of your Application
subclass? I bet you can refactor that class so that Application
is no longer a direct dependency for it - perhaps you merely need a Context. If you merely need singletons at app-scope, you can simply make a module with @Singleton
@Provides
methods and install it in your application component.
If, after all this, you find you must @Provide
your subclass you can create a new module that doesn't include any others:
@Module //don't include other modules here
class AppModule {
private final App app;
public AppModule(App app) {
this.app = app;
}
@Provides
@Singleton
App app() {
return app;
}
}
And install it in your app-level component:
//inside your App class
DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build()
.inject(this);
You would not need the AppModule if you implemented the following in your Application
:
public class App extends DaggerApplication {
private AndroidInjector<App> appInjector;
@dagger.Component(modules = {
AndroidSupportInjectionModule.class,
AppModule.class
})
public interface Component extends AndroidInjector<App> {
@dagger.Component.Builder
abstract class Builder extends AndroidInjector.Builder<App> {}
}
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerApp_Component
.builder()
.username("Username from application")
.create(this);
}
}
Now App
will be a dependency on the global scope and can be used in every module linked to the @Component
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.