MVP Presenter没有正确注入

5
我正在尝试将一些Mindorks advanced MVP样例转换为Kotlin,并同时学习Kotlin和Dagger 2,但是遇到了Dagger2编译问题。这里有很多类,但我很接近成功!请忽略凌乱的代码,一旦编译完成,我会检查每个类。如果有遗漏,请告诉我。错误在于我的Presenter类没有正确注入到Activity中。错误信息如下:
e: D:\_Dev\repo\app\build\tmp\kapt3\stubs\debug\com\xxx\di\component\ActivityComponent.java:8: error: com.xxx.login.LoginMVP.Presenter<com.xxx.login.LoginMVP.View,? extends com.xxx.login.LoginMVP.Interactor> cannot be provided without an @Provides- or @Produces-annotated method.
e: 

e:     public abstract void inject(@org.jetbrains.annotations.NotNull()
e:                          ^
e:       com.xxx.login.LoginMVP.Presenter<com.xxx.login.LoginMVP.View,? extends com.xxx.login.LoginMVP.Interactor> is injected at
e:           com.xxx.login.LoginActivity.presenter
e:       com.xxx.login.LoginActivity is injected at
e:           com.xxx.di.component.ActivityComponent.inject(activity)
e: java.lang.IllegalStateException: failed to analyze: org.jetbrains.kotlin.kapt3.diagnostic.KaptError: Error while annotation processing

编辑:

这里是一个存储库,其中包含最新的Android Studio金丝雀版本构建的失败代码

BaseActivity.kt

abstract class BaseActivity : AppCompatActivity(), MvpView {

    val activityComponent: ActivityComponent by lazy {
        DaggerActivityComponent.builder()
                .applicationComponent((application as App).applicationComponent)
                .activityModule(ActivityModule(this))
                .build()
    }
}

BasePresenter.kt

open class BasePresenter<V : MvpView, out I: MvpInteractor>
@Inject constructor(private val mvpInteractor: I) : MvpPresenter<V, I> {

    private var mvpView: V? = null

    override fun onAttach(mvpView: V) {
        this.mvpView = mvpView
    }

    override fun onDetach() {
        mvpView = null
    }

    override fun getMvpView(): V? {
        return mvpView
    }

    override fun getInteractor(): I {
        return mvpInteractor
    }

}

MvpPresenter.kt(MvpView和MvpInteractor是基本的空接口)
interface MvpPresenter<V: MvpView, out I: MvpInteractor> {

    fun onAttach(mvpView: V)

    fun onDetach()

    fun getMvpView(): V?

    fun getInteractor(): I
}

App.kt

class App: Application() {

    lateinit var applicationComponent: ApplicationComponent

    override fun onCreate() {
        super.onCreate()
        applicationComponent = DaggerApplicationComponent.builder()
                .applicationModule(ApplicationModule(this)).build()

        applicationComponent.inject(this)
    }

    fun getComponent(): ApplicationComponent {
        return applicationComponent
    }

    fun setComponent(applicationComponent: ApplicationComponent) {
        this.applicationComponent = applicationComponent
    }
}

ApplicationComponent.kt

@Singleton
@Component(modules = arrayOf(ApplicationModule::class))
interface ApplicationComponent {

    fun inject(app: App)

    @ApplicationContext fun context(): Context

    fun application(): Application

    //Pref helper
    //Api helper
}

ApplicationModule.kt

@Module
class ApplicationModule(val application: Application) {

    @Provides
    @ApplicationContext
    fun provideContext(): Context = application

    @Provides
    fun provideApplication(): Application = application

    //Provide api helper

    //Provide pref helper

    //Provide api key etc.
}

ActivityModule.kt

@Module
class ActivityModule(val activity: AppCompatActivity) {

    @Provides
    fun provideContext(): Context = activity

    @Provides
    fun provideActivity(): AppCompatActivity = activity

    @Provides
    fun provideLoginPresenter(presenter: LoginPresenter<LoginMVP.View, LoginMVP.Interactor>):
            LoginMVP.Presenter<LoginMVP.View, LoginMVP.Interactor> {
        return presenter
    }

    @Provides
    fun provideLoginMvpInteractor(interactor: LoginInteractor):
            LoginMVP.Interactor {
        return interactor
    }

}

ActivityComponent.kt

@PerActivity
@Component(dependencies = arrayOf(ApplicationComponent::class), modules = arrayOf(ActivityModule::class))
interface ActivityComponent {

    fun inject(activity: LoginActivity)
}

LoginActivity.kt

class LoginActivity : BaseActivity(), LoaderCallbacks<Cursor>, LoginMVP.View {

    @Inject lateinit var presenter: LoginMVP.Presenter<LoginMVP.View, LoginMVP.Interactor>

    private var authTask: UserLoginTask? = null


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        activityComponent.inject(this)

        email_sign_in_button.setOnClickListener { presenter.onServerLoginClick(email.text.toString(), password.text.toString()) }

        presenter.onAttach(this)
    }
}

LoginMVP.kt

interface LoginMVP {

    interface Interactor : MvpInteractor {

    }

    @PerActivity
    interface Presenter<V : LoginMVP.View, out I : LoginMVP.Interactor>
        : MvpPresenter<V, I> {

        fun onServerLoginClick(email: String, password: String)

    }

    interface View : MvpView {
        fun openMainActivity()
    }
}

你介意把你当前的状态推送到Github吗?我想看一下。 - fweigl
感谢@Ascorbin,我现在已经添加了一个仓库链接。它是使用最新的canary Android Studio构建的,所以希望这不是一个问题。 - Daniel Wilson
1个回答

3
这不是一个完整的答案,但非常接近。问题在于out修饰符。使用这个修饰符时,Dagger尝试注入。
com.xxx.login.LoginMVP.Presenter<com.xxx.login.LoginMVP.View,? extends com.xxx.login.LoginMVP.Interactor>

但是你只提供了

  com.xxx.login.LoginMVP.Presenter<com.xxx.login.LoginMVP.View, com.xxx.login.LoginMVP.Interactor>  

(在函数provideLoginPresenter中)。

如果从PresenterBasePresenterLoginPresenter中删除所有的out修饰符,它就能编译并工作了。

我不确定为什么Dagger尝试注入错误类型或无法理解它是相同类型。看起来像是注释处理时出现的错误。因此,最简单的解决方案是不要在Dagger中使用out修饰符。


干得好,谢谢你。我只是按照AS告诉我的去做,结果让我烦恼了大约6个小时 :) - Daniel Wilson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接