尝试使用匕首解决依赖关系周期
作者:互联网
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> ;,但是如果您希望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