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

在网上冲浪之后,似乎没有类似的问题,它正在吃掉我。 在学习使用Dagger 2进行dependency injection的过程中,我试图将Java的一个例子翻译成Kotlin。 该项目在Java编译罚款,但使用Kotlin,不喜欢javax.inject.Provider类,并无法建立。

什么不见​​了? 这里的提供者类的使用是否对Kotlin不正确?

这是Gradle事件日志中的错误:

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

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

  class ActivityInjector @Inject internal constructor(private val activityInjectors: Map<Class, Provider<AndroidInjector.Factory>>){ private val cache = HashMap<String, AndroidInjector>() 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).inject(activity) return } val injectorFactory = activityInjectors[activity.javaClass]?.get() as AndroidInjector.Factory 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 } 

建立良好的衡量标准:

 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 override fun onCreate() { super.onCreate() DaggerRepoTrendsAppComponent.builder() .repoTrendsAppModule(RepoTrendsAppModule(this)) .build() .inject(this) } override fun activityInjector(): AndroidInjector? { return dispatchingActivityInjector } } 

和你的组件:

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

听起来像你的模块上缺少@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" }