简体   繁体   English

Dagger 2.11依赖周期

[英]Dagger 2.11 Dependency Cycle

Using Dagger 2.11, the following code returns "Error:[dagger.android.AndroidInjector.inject(T)] Found a dependency cycle:". 使用Dagger 2.11,以下代码返回“错误:[dagger.android.AndroidInjector.inject(T)]找到一个依赖周期:”。 This is happening because the provideApp method has the argument "App app". 发生这种情况是因为ProvideApp方法具有参数“ 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. 从我之前看到的示例中,将应用程序的实例保留在模块中并将其用于其他提供者的做法是一种常见的做法,但是由于此模块类现在是抽象的,因此不能用作@Provide方法需要是静态的。

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. 但是,这不起作用,因为AppModule现在是一个抽象类,并且如果我在不使用static关键字的情况下使用@Provides Authenticator authenticator ProvideAuthenticator(),则该应用程序将无法编译。 If I use the static keyword, then I can't access the non-static application field. 如果使用static关键字,则无法访问非静态应用程序字段。

Your code: 您的代码:

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

means "provide App using App as a dependency". 表示“使用App作为依赖来提供App”。 In other words, you want to provide App but you need App first. 换句话说,您想要提供App但首先需要App 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. 解决此问题的最佳方法是遵循Demeter规则,完全不提供Application单例。

Why does your AuthenticatorImpl need to know the concrete type of your Application subclass? 为什么AuthenticatorImpl需要知道Application子类的具体类型? I bet you can refactor that class so that Application is no longer a direct dependency for it - perhaps you merely need a Context. 我敢打赌,您可以重构该类,以便Application不再是它的直接依赖项-也许您只需要一个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. 如果仅在应用程序范围内需要单例,则可以@Singleton @Provides方法简单地创建一个模块并将其安装在应用程序组件中。

If, after all this, you find you must @Provide your subclass you can create a new module that doesn't include any others: 在所有这些之后,如果您发现必须@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;
    }
} 

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 : 如果在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);
    }
}

Now App will be a dependency on the global scope and can be used in every module linked to the @Component . 现在, App将依赖于全局范围,并且可以在链接到@Component每个模块中使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM