dagger-android 2.16

我的匕首模块中存在依赖循环错误。我想我知道问题是什么,但不知道如何解决。
这是错误消息:
Found a dependency cycle:
  public interface LoginFragmentSubcomponent extends AndroidInjector<LoginFragment> {
     presentation.login.request.LoginRequest is injected at
              mobileui.login.di.LoginActivityModule.provideLoginResponseListener(…, loginRequest)
          presentation.login.response.LoginResponseListener is injected at
              mobileui.login.di.LoginActivityModule.provideLoginRequest(…, loginPresenter)
          presentation.login.request.LoginRequest is injected at
              mobileui.login.di.LoginActivityModule.provideLoginPresenter(…, loginRequest)
          mobileui.login.LoginPresenter is injected at
              mobileui.login.LoginFragment.loginPresenter

这是下面的模块,我在这里得到错误
@Module
class LoginActivityModule {
    @Reusable
    @Provides
    fun provideLoginPresenter(loginRequest: LoginRequest): LoginPresenter {
        return LoginPresenterImp(loginRequest)
    }

    @Reusable
    @Provides
    fun provideLoginResponseListener(loginRequest: LoginRequest): LoginResponseListener {
        LoginPresenterImp(loginRequest)
    }

    @Reusable
    @Provides
    fun provideLoginRequest(loginUser: LoginUser,
                            loginPresenter: LoginResponseListener): LoginRequest {
        return LoginRequestImp(loginUser, loginPresenter)
    }
}

我的loginPresenterImp实现了loginResponseListener,我想将其传递给loginRequestimp类,以便将其用作回调。
class LoginPresenterImp(private val loginRequest: LoginRequest) :
    BasePresenterImp<LoginView>(),
    LoginPresenter,
    LoginResponseListener {
}

loginResponseListener在这里传递:
class LoginRequestImp(
    private val loginUser: LoginUser,
    private val loginResponseListener: LoginResponseListener)
    : LoginRequest {
}

多谢提前,

最佳答案

如评论中所述:
您需要loginResponseListener来创建loginRequest,并且需要loginRequest来创建loginResponseListener。所以,你得到了错误。
在loginrequestimp(loginuser,loginpresenter)中创建loginrequest时,loginpresenter是loginresponselistener类型的构造函数的参数。你应该试着消除这种依赖。可能是您可以稍后从演示者设置侦听器
在您的回复中,在这些评论之间:
已在provideloginrequest中创建loginrequest
但这就是发生的事:
您的loginFragment尝试插入loginPresenter。
在注入loginpresenter之前,需要创建loginrequest。
在创建loginrequest之前,您需要loginuser和loginrequestlistener。
在创建loginRequestListener(已实现为loginPresentImpl)之前,需要loginRequest。
您正在创建loginrequest,因此dagger放弃并正确报告循环引用。
重申一下:尽管您已经正确地使用接口设置了绑定,但Dagger无法创建任何绑定,因为要调用任何一个构造函数,都必须创建另一个构造函数。这不是Dagger的问题:如果类A的构造函数获取B的一个实例,而类B的构造函数获取A的一个实例,那么在尊重它们的构造函数参数的情况下,也不能手动构造它们中的任何一个。
正如ayush所建议的,不要让loginrequest注入loginresponselistener。相反,创建一个类似于setLoginResponseListener的方法,loginpresenterimp可以调用该方法。我也推荐这种方法,部分原因是Ayush:您希望绝对确保充当loginpresenter的loginpresenterimp实例与充当loginresponselistener的实例相同。
作为替代方案,您可以插入Provider<LoginPresenter>而不是LoginResponseListener,并更改loginrequestimp以接受提供者。(您也可以插入Provider<LoginResponseListener>,但如果希望loginResponseListener与您的loginPresenter实例相同,则不应显式调用loginPresenterImp构造函数。理想情况下,您需要切换到@Binds,或者至少让您的@Provides方法注入loginpresenter。)您可以注入提供者,因为@Reusable has weaker semantics than you want,它可以解决您的问题,因为dagger可以通过Provider<T>,而无需尝试创建<T>。即使您将绑定保留为Provider<T>,这在技术上似乎也会起作用,但是在多线程环境中T不能保证您总是收到与您的loginpresenter相同的loginrequestlistener实例,或者您将收到每个loginframge的新loginpresenter。NT。如果您想保证这一点,您可以查看a @Reusable is automatically bound for every class @Reusable that Dagger knows how to provide

10-03 00:45