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。