MVP Presenter 未正确注入
MVP Presenter not injected correctly
我正在通过尝试将 Mindorks advanced MVP sample 中的一些内容转换为 Kotlin 来同时学习 Kotlin 和 Dagger 2,但我遇到了 Dagger2 编译问题。我在这里 classes 游泳,但距离很近!不要介意这些不整洁,我打算在编译后梳理每个 class 。如果缺少什么,请告诉我。错误归结为我的演示者 class 没有被正确注入 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
编辑:
Here is a repo with the failing code,使用 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()
}
}
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()
}
}
这不是一个完整的答案,但非常接近。
问题出在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
中)。
因此,如果删除所有 out
修改(来自 Presenter
、BasePresenter
、LoginPresenter
),它会开始编译和工作。
我不确定为什么 Dagger 尝试注入错误的类型或无法理解它是同一类型。注释处理时看起来像错误。所以最简单的解决方案 - 不要使用 out
修饰符
用匕首。
我正在通过尝试将 Mindorks advanced MVP sample 中的一些内容转换为 Kotlin 来同时学习 Kotlin 和 Dagger 2,但我遇到了 Dagger2 编译问题。我在这里 classes 游泳,但距离很近!不要介意这些不整洁,我打算在编译后梳理每个 class 。如果缺少什么,请告诉我。错误归结为我的演示者 class 没有被正确注入 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
编辑:
Here is a repo with the failing code,使用 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()
}
}
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()
}
}
这不是一个完整的答案,但非常接近。
问题出在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
中)。
因此,如果删除所有 out
修改(来自 Presenter
、BasePresenter
、LoginPresenter
),它会开始编译和工作。
我不确定为什么 Dagger 尝试注入错误的类型或无法理解它是同一类型。注释处理时看起来像错误。所以最简单的解决方案 - 不要使用 out
修饰符
用匕首。