Kotlin 和 Dagger 2:使用 Provider 类的问题



在互联网上搜索后,似乎没有类似的问题,它正在吞噬我。在使用 Dagger 2 学习依赖注入的过程中,我正在尝试将一个示例从 Java 转换为 Kotlin。该项目在Java中编译良好,但是使用Kotlin,不喜欢javax.inject.Provider类并且无法构建。

缺少什么?这里的 Kotlin 对 Provider 类的使用不正确吗?

以下是 Gradle 事件日志中的错误:

repositorytrendscustom_implementationsRepoTrendsAppComponent.java:8: error: java.util.Map<java.lang.Class<? extends android.app.Activity>,? extends javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.app.Activity>>> cannot be provided without an @Provides-annotated method.

这是有问题的文件。内部构造函数的参数 (Map( 是成功构建的决定性因素:

    class ActivityInjector
@Inject internal constructor(private val activityInjectors: Map<Class<out Activity>, Provider<AndroidInjector.Factory<out Activity>>>){
         private val cache = HashMap<String, AndroidInjector<out Activity>>()
         internal fun inject(activity: Activity) {
             if (activity !is RepoTrendActivity) {
                 throw IllegalArgumentException("Activity must extend BaseActivity")
             }
             val instanceId = activity.getInstanceID
             if (cache.containsKey(instanceId)) {
                 (cache[instanceId] as AndroidInjector<Activity>).inject(activity)
                 return
             }
             val injectorFactory = activityInjectors[activity.javaClass]?.get() as AndroidInjector.Factory<Activity>
             val injector = injectorFactory.create(activity)
             cache.put(instanceId, injector)
             injector.inject(activity)
         }
         internal fun clear(activity: Activity) {
             if (activity !is RepoTrendActivity) {
                 throw IllegalArgumentException("Activity must extend BaseActivity")
             }
             cache.remove(activity.getInstanceID)
         }
         companion object {
             internal operator fun get(context: Context): ActivityInjector{
                 return (context.applicationContext as RepoTrendsApp).activityInjector
             }
         }
}

以下是与 Gradle 构建错误日志相关的其余类:

@Singleton
@Component(modules = arrayOf(
        RepoTrendsAppModule::class
))
interface RepoTrendsAppComponent {
    fun inject(repoTrendsApp: RepoTrendsApp)
}

自定义应用程序文件:

class RepoTrendsApp: Application(){
    @Inject lateinit var activityInjector: ActivityInjector
}

Build.gradle for good measure:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
    compileSdkVersion 26
    defaultConfig {
        applicationId 'com.inviscidlabs.repositorytrends'
        minSdkVersion 21
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
    kapt {
        generateStubs = true
    }
}
dependencies {
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
    implementation "com.android.support:design:$supportLibraryVersion"
    implementation "com.google.dagger:dagger:$daggerVersion"
    implementation "com.google.dagger:dagger-android-support:$daggerVersion"
    kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
    kapt "com.google.dagger:dagger-compiler:$daggerVersion"
    implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
    implementation "com.squareup.retrofit2:converter-moshi:$retrofitVersion"
    implementation "com.squareup.moshi:moshi:$moshiVersion"
    kapt "com.ryanharter.auto.value:auto-value-moshi:$autoValueMoshiVersion"
    compileOnly "com.ryanharter.auto.value:auto-value-moshi-annotations:$autoValueMoshiVersion"
    compileOnly "com.google.auto.value:auto-value:$autoValueVersion"
    annotationProcessor "com.google.auto.value:auto-value:$autoValueVersion"
    implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion"
    implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion"
    implementation "com.jakewharton.rxrelay2:rxrelay:$rxRelayVersion"
    //Drop in replacement for Fragments
    implementation "com.bluelinelabs:conductor:$conductorVersion"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
}

根据要求,RepoTrendsAppModule

import android.app.Application
import android.content.Context
import dagger.Module
import dagger.Provides

@Module
class RepoTrendsAppModule(val application: Application){
    @Provides
    fun provideApplicationContext(): Context = application
}

你不需要你的ActivityInjector类。 按如下方式修改应用程序类:

class RepoTrendsApp: Application(), HasActivityInjector {
    @Inject
    internal lateinit var dispatchingActivityInjector: DispatchingAndroidInjector<Activity>
    override fun onCreate() {
    super.onCreate()
        DaggerRepoTrendsAppComponent.builder()
            .repoTrendsAppModule(RepoTrendsAppModule(this))
            .build()
            .inject(this)
    }
    override fun activityInjector(): AndroidInjector<Activity>? {
        return dispatchingActivityInjector
    }
}

和您的组件:

@Singleton
@Component(modules = arrayOf(
        AndroidSupportInjectionModule::class,
        RepoTrendsAppModule::class
))
interface RepoTrendsAppComponent : AndroidInjector<RepoTrendsApp>

听起来您的模块上缺少一些@Provides注释。下面是一个 Kotlin/Android/Dagger 2 模块定义示例:

@Module
class MyAndroidModule(private val application: Application) {
    @Provides
    @Singleton
    @CustomInjectionAnnotation
    fun provideApplicationContext(): Context = application
    @Provides
    @Singleton
    fun provideLocationManager(): LocationManager =
            application.getSystemService(Context.LOCATION_SERVICE) as LocationManager
    @Provides
    @Singleton
    @Named("version")
    fun provideVersionString(): String = "beta"    
}

最新更新