Kotlin 和 Dagger 2:使用 Provider 的问题 class
Kotlin and Dagger 2: Issues using Provider class
在网上搜索后,似乎没有类似的问题,它正在吃我。在使用 Dagger 2 学习依赖注入的过程中,我试图将一个例子从 Java 翻译成 Kotlin。该项目在 Java 中编译良好,但使用 Kotlin,不喜欢 javax.inject.Provider class 并且无法构建。
缺少什么?此处对 Kotlin 使用 Provider class 不正确吗?
这是来自 Gradle 事件日志的错误:
repositorytrends\custom_implementations\RepoTrendsAppComponent.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 构建错误日志相关的其余 classes:
@Singleton
@Component(modules = arrayOf(
RepoTrendsAppModule::class
))
interface RepoTrendsAppComponent {
fun inject(repoTrendsApp: RepoTrendsApp)
}
自定义应用程序文件:
class RepoTrendsApp: Application(){
@Inject lateinit var activityInjector: ActivityInjector
}
Build.gradle 好的衡量标准:
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
}
听起来您的模块中缺少某些 @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"
}
您不需要 ActivityInjector
class。按如下方式修改您的应用程序 class:
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>
在网上搜索后,似乎没有类似的问题,它正在吃我。在使用 Dagger 2 学习依赖注入的过程中,我试图将一个例子从 Java 翻译成 Kotlin。该项目在 Java 中编译良好,但使用 Kotlin,不喜欢 javax.inject.Provider class 并且无法构建。
缺少什么?此处对 Kotlin 使用 Provider class 不正确吗?
这是来自 Gradle 事件日志的错误:
repositorytrends\custom_implementations\RepoTrendsAppComponent.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 构建错误日志相关的其余 classes:
@Singleton
@Component(modules = arrayOf(
RepoTrendsAppModule::class
))
interface RepoTrendsAppComponent {
fun inject(repoTrendsApp: RepoTrendsApp)
}
自定义应用程序文件:
class RepoTrendsApp: Application(){
@Inject lateinit var activityInjector: ActivityInjector
}
Build.gradle 好的衡量标准:
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
}
听起来您的模块中缺少某些 @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"
}
您不需要 ActivityInjector
class。按如下方式修改您的应用程序 class:
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>