其他分享
首页 > 其他分享> > 尝试使用匕首解决依赖关系周期

尝试使用匕首解决依赖关系周期

作者:互联网

dagger-android 2.16

我的Dagger模块中有一个依赖周期错误.我想我知道问题出在哪里,但不确定如何解决.

这是错误消息:

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 {
}

提前谢谢了,

解决方法:

如注释中所述的Ayush

You need LoginResponseListener to create LoginRequest and you need LoginRequest to create LoginResponseListener. So, you are getting the error.

When you are creating LoginRequest in LoginRequestImp(loginUser, loginPresenter), loginPresenter is a parameter to the constructor of type LoginResponseListener. You should try to eliminate this dependency. May be you can set the listener later from the presenter

在这些评论之间的回复中:

LoginRequest has been created in provideLoginRequest

但这是正在发生的事情:

>您的LoginFragment尝试注入LoginPresenter.
>在注入LoginPresenter之前,您需要创建一个LoginRequest.
>在创建LoginRequest之前,您需要一个LoginUser和一个LoginRequestListener.
>在创建LoginRequestListener(已实现为LoginPresenterImpl)之前,您需要一个LoginRequest.
>您正在创建LoginRequest,因此Dagger放弃并正确报告了循环引用.

重申一下:即使您已正确使用接口设置了绑定,Dagger也无法创建任何一个接口,因为调用任何一个构造函数都必须创建另一个.这不是Dagger的问题:如果类A的构造函数采用B的实例,而类B的构造函数采用A的实例,则在尊重其构造函数参数的同时,您也无法手动构造它们中的任何一个.

正如Ayush建议的那样,不要让LoginRequest注入LoginResponseListener.而是创建一个类似setLoginResponseListener的方法,LoginPresenterImp可以调用该方法.我也推荐这种方法,部分原因是@Reusable has weaker semantics than you want:您要绝对确保充当LoginPresenter的LoginPresenterImp实例与充当LoginResponseListener的实例相同.

或者,您可以注入Provider< LoginPresenter>.而不是LoginResponseListener,并将LoginRequestImp更改为也接受提供者. (您也可以注入Provider< LoginResponseListener&gt ;,但是如果您希望LoginResponseListener与LoginPresenter实例相同,则不应显式调用LoginPresenterImp构造函数.理想情况下,您希望切换到@Binds或在允许您注入提供程序,因为a Provider<T> is automatically bound for every class <T> that Dagger knows how to provide,它可以解决您的问题,因为Dagger可以传递Provider< T>.从技术上讲,即使您将绑定保留为@Reusable,这在技术上似乎仍然有效,但是在多线程环境中,@ Reusable不能保证您始终收到与LoginPresenter相同的LoginRequestListener实例,或者您将为每个LoginFragment收到一个新的LoginPresenter.如果您想保证这一点,可以查看custom scopes.

标签:dagger,dagger-2,android
来源: https://codeday.me/bug/20191024/1923689.html