Dagger 2.11依赖循环

时间:2017-08-02 20:12:50

标签: android dagger-2

使用Dagger 2.11,以下代码返回“错误:[dagger.android.AndroidInjector.inject(T)]找到一个依赖循环:”。发生这种情况是因为provideApp方法具有参数“App app”。如果我删除它并执行直接提供应用程序实例的脏黑客,则代码将编译并运行。

从我以前见过的例子中,过去常常将应用程序的实例保存在模块中并将其用于其他提供程序,但由于此模块类现在是抽象的,因此不能用作@Provide方法需要是静态的。

我该如何解决这个问题?

@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);
     }
}

修改

我需要实现的基本上是这种行为:

@Module(includes = AndroidInjectionModule.class)
public class AppModule {

    private App application;

    AppModule(App app) {
        application = app;
    }

    @Provides
    Authenticator provideAuthenticator() {
        return new AuthenticatorImpl(application);
    }
}

但是,这不起作用,因为AppModule现在是一个抽象类,如果我使用没有static关键字的@Provides Authenticator provideAuthenticator(),app将无法编译。如果我使用static关键字,那么我无法访问非静态应用程序字段。

2 个答案:

答案 0 :(得分:3)

您的代码:

 @Provides
 @Singleton
 static App provideApp(App app) {
    return app;
 }

表示"使用App作为依赖关系提供App"。换句话说,您希望提供App,但首先需要App。因此你的周期。

此问题的最佳解决方案是遵循Demeter规则,而不是提供Application单例。

为什么您的AuthenticatorImpl需要知道Application子类的具体类型?我打赌你可以重构那个类,以便Application不再是它的直接依赖 - 也许你只需要一个Context。如果您只需要在应用程序范围内使用单例,则可以使用@Singleton @Provides方法创建一个模块,并将其安装在应用程序组件中。

如果在此之后,您发现必须@Provide您的子类,则可以创建一个不包含任何其他模块的新模块:

@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;
    }
} 

并将其安装在您的应用级组件中:

    //inside your App class

    DaggerAppComponent.builder()
            .appModule(new AppModule(this))
            .build()
            .inject(this);

答案 1 :(得分:0)

如果您在Application中实施了以下内容,则不需要AppModule:

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);
    }
}

现在App将依赖于全局范围,并且可以在链接到@Component的每个模块中使用。