2017-07-28 69 views
4

我正在學習Kotlin和Dagger 2,試圖將Mindorks advanced MVP sample中的一些轉換爲Kotlin,但我有Dagger2編譯問題。我在這裏上課,但非常接近!不介意不整潔,我打算在編譯完成後梳理每個類。如果有什麼遺漏,請讓我知道。錯誤歸結爲我的演示者類未正確注入到活動中。該錯誤內容如下:MVP演示者未正確注入

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工作室的最新金絲雀構建內置

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() 
    } 
} 
+0

你介意把你目前的狀態推到Github上嗎?想看看。 – FWeigl

+0

謝謝@Ascorbin,我現在添加了回購鏈接。它是用最新的Canary Android Studio構建的,所以希望這不是問題。 –

回答

3

這不是一個完整的答案,但非常接近。

問題在out修飾符中。有了這個修改匕首試圖注入

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修改(從PresenterBasePresenter,LoginPresenter)它開始編譯和工作。

我不知道爲什麼Dagger嘗試注入錯誤的類型或無法理解它是相同的類型。它看起來像註釋處理時的錯誤。所以最簡單的解決方案 - 不要使用out修改器 與Dagger。

+0

非常感謝。我只是做了我告訴我的事情,並導致我約6小時的悲傷:) –