MVP Presenter注入不正确

Dan*_*son 5 android dependency-injection kotlin dagger-2

我正在尝试通过将Mindorks的一些高级MVP样本转换为Kotlin 同时学习Kotlin和Dagger 2,但遇到了Dagger2的编译问题。我在这里上课游泳,但是距离很近!别介意那些笨拙的事情,我打算在每个班级编译后对其进行梳理。如果缺少什么,请告诉我。该错误归结为我的演示者类未正确注入到活动中。错误内容如下:

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
Run Code Online (Sandbox Code Playgroud)

编辑:

这是带有失败代码的存储库,该代码是使用最新的Android Studio Canary版本构建的

BaseActivity.kt

abstract class BaseActivity : AppCompatActivity(), MvpView {

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

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
    }

}
Run Code Online (Sandbox Code Playgroud)

MvpPresenter.kt(MvpView和MvpInteractor是基本的空接口)

interface MvpPresenter<V: MvpView, out I: MvpInteractor> {

    fun onAttach(mvpView: V)

    fun onDetach()

    fun getMvpView(): V?

    fun getInteractor(): I
}
Run Code Online (Sandbox Code Playgroud)

应用程式

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

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.
}
Run Code Online (Sandbox Code Playgroud)

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
    }

}
Run Code Online (Sandbox Code Playgroud)

ActivityComponent.kt

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

    fun inject(activity: LoginActivity)
}
Run Code Online (Sandbox Code Playgroud)

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

登录MVP.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()
    }
}
Run Code Online (Sandbox Code Playgroud)

Dmi*_*nko 3

这不是一个完整的答案,但非常接近。

问题出在out修改器上。使用此修改器 Dagger 尝试注入

com.xxx.login.LoginMVP.Presenter<com.xxx.login.LoginMVP.View,? extends com.xxx.login.LoginMVP.Interactor>
Run Code Online (Sandbox Code Playgroud)

但你只提供

  com.xxx.login.LoginMVP.Presenter<com.xxx.login.LoginMVP.View, com.xxx.login.LoginMVP.Interactor>  
Run Code Online (Sandbox Code Playgroud)

(在函数中provideLoginPresenter)。

因此,如果删除所有out修改(来自PresenterBasePresenterLoginPresenter),它将开始编译并工作。

我不确定为什么 Dagger 尝试注入错误的类型或无法理解它是相同的类型。它看起来像是注释处理时的错误。所以最简单的解决方案 - 不要将out修饰符与 Dagger 一起使用。