无法 运行 kotlin with dagger 2

Unable to run kotlin with dagger 2

我是 kotlin 和 dagger 2 的新手。我尝试在 Android Java 中关注此 guide。但错误被抛出...

Error:Execution failed for task ':app:kaptDebugKotlin'. Internal compiler error. See log for more details

我做错了什么?

申请

class App : Application() {

    val netComponent: NetComponent by lazy {
        DaggerNetComponent.builder()
                .appModule(AppModule(this)) // This also corresponds to the name of your module: %component_name%Module
                .netModule(NetModule("https://api.github.com"))
                .build()
    }

    override fun onCreate() {
        super.onCreate()
    }

    fun netComponent() : NetComponent = netComponent
}

网络组件

@Singleton
@Component(modules= arrayOf(AppModule::class, NetModule::class))
interface NetComponent {
    fun inject(activity: HomeActivity)
}

网络模块

@Module()
class NetModule(baseUrl: String) {

    val mBaseUrl: String = baseUrl;

    @Provides
    @Singleton
    fun providedSharedPreferences(app: Application): SharedPreferences {
        return PreferenceManager.getDefaultSharedPreferences(app);
    }

    @Provides
    @Singleton
    fun provideOkHttpCache(app: Application): Cache {
        val cacheSize = 10 * 1024 * 1024 // 10 MiB
        return Cache(app.cacheDir, cacheSize.toLong())
    }

    @Provides
    @Singleton
    fun providedGson(): Gson {
        return GsonBuilder()
                .excludeFieldsWithoutExposeAnnotation()
                .create();
    }

    @Provides
    @Singleton
    fun provideOkHttpClient(cache: Cache): OkHttpClient {
        return OkHttpClient.Builder()
                .cache(cache)
                .build();
    }

    @Provides
    @Singleton
    fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(mBaseUrl)
                .client(okHttpClient)
                .build()
    }

}

AppModule

@Module()
class AppModule(val app: App) {

    @Provides
    @Singleton
    fun provideApp() = app

}

AppComponent

@Singleton
@Component(modules = arrayOf(AppModule::class))
interface AppComponent {

    fun inject(app: App)
}

最后,HomeActivity

class HomeActivity : AppCompatActivity() {

    @Inject var sharedPreferences: SharedPreferences? = null;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)
        (application as App).netComponent.inject(this)
    }
}

It's build failed when I start using @Inject annotation to HomeActivity Class.

Gradle应用程序

apply plugin: 'com.android.application'

apply plugin: 'kotlin-kapt'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
    defaultConfig {
        applicationId "com.viinsoft.mobile.app"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    // App's dependencies, including test
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    kapt "com.google.dagger:dagger-compiler:$dragger"
    implementation "com.google.dagger:dagger:$dragger"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation "com.android.support:design:$supportLibraryVersion"
    implementation "com.android.support.constraint:constraint-layout:$constraintLayout"
    implementation "com.github.bumptech.glide:glide:$glideVersion"
    implementation "com.squareup.retrofit2:retrofit:$retrofit"
    implementation "com.squareup.retrofit2:converter-gson:$retrofit"
    implementation "com.google.code.gson:gson:$gson"
    implementation "com.google.guava:guava:$guavaVersion"
    implementation "com.android.support.test.espresso:espresso-idling-resource:$espressoVersion"

    // Dependencies for local unit tests
    testCompile "junit:junit:$junitVersion"
    testCompile "org.mockito:mockito-all:$mockitoVersion"
    testCompile "org.hamcrest:hamcrest-all:$hamcrestVersion"
    testCompile "org.powermock:powermock-module-junit4:$powerMockito"
    testCompile "org.powermock:powermock-api-mockito:$powerMockito"

    // Android Testing Support Library's runner and rules
    androidTestCompile "com.android.support.test:runner:$runnerVersion"
    androidTestCompile "com.android.support.test:rules:$rulesVersion"

    // Espresso UI Testing dependencies.
    androidTestCompile ("com.android.support.test.espresso:espresso-core:$espressoVersion", {
        exclude group: 'com.google.code.findbugs'
    })
    androidTestCompile ("com.android.support.test.espresso:espresso-contrib:$espressoVersion", {
        exclude group: 'com.google.code.findbugs'
    })
    androidTestCompile ("com.android.support.test.espresso:espresso-intents:$espressoVersion", {
        exclude group: 'com.google.code.findbugs'
    })
}

kapt {
    generateStubs = true
}

Gradle 项目

buildscript {
    ext.kotlin_version = '1.1.4-3'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-beta4'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

ext {
    // Sdk and tools
    minSdkVersion = 16
    targetSdkVersion = 26
    compileSdkVersion = 26
    buildToolsVersion = '26.0.1'

    // App dependencies
    supportLibraryVersion = '26.0.2'
    constraintLayout = '1.0.2'
    retrofit = '2.3.0'
    gson = '2.8.1'
    glideVersion = '4.0.0'
    guavaVersion = '23.0-android'
    dragger = '2.11'

    // Dependencies for local unit tests
    junitVersion = '4.12'
    mockitoVersion = '1.10.19'
    powerMockito = '1.7.1'
    hamcrestVersion = '1.3'

    // Android Testing Support Library's runner and rules
    runnerVersion = '1.0.0'
    rulesVersion = '1.0.0'

    // Espresso UI Testing dependencies.
    espressoVersion = '3.0.1'
}

编辑GRADLE日志

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:kaptDebugKotlin'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:100)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:63)
        at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)
        at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.run(DefaultTaskGraphExecuter.java:248)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:197)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:107)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:124)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access0(DefaultTaskPlanExecutor.java:80)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.execute(DefaultTaskPlanExecutor.java:105)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.execute(DefaultTaskPlanExecutor.java:99)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:625)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:580)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:99)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: org.gradle.api.GradleException: Internal compiler error. See log for more details
        at org.jetbrains.kotlin.gradle.tasks.TasksUtilsKt.throwGradleExceptionIfError(tasksUtils.kt:9)
        at org.jetbrains.kotlin.gradle.internal.KaptTask.compile(KaptTask.kt:71)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
        at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.doExecute(DefaultTaskClassInfoStore.java:141)
        at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:134)
        at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:121)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:731)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:705)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.run(ExecuteActionsTaskExecuter.java:122)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:197)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:107)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:111)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
        ... 27 more

我在 Kotlin 上使用 Dagger2,尝试这样做:

@Inject lateinit var sharedPreferences: SharedPreferences

而不是:

@Inject var sharedPreferences: SharedPreferences? = null

这样我也解决了Butterknife的问题

EDIT: 打开 Gradle 控制台,可能会报错:

通过更新 AppModule 解决

from App (which extend Application) to Application

来自

@Module()
class AppModule(val app: App) {

    @Provides
    @Singleton
    fun provideApp() = app

}

@Module()
class AppModule(val app: Application) {

    @Provides
    @Singleton
    fun provideApp() = app

}

我不知道为什么,但也许NetModule.class,一些提供的方法需要应用程序作为输入参数,所以Dragger可能不知道应用程序是从应用程序扩展的class,导致失败已解决注入问题。

任何人都可以证实这个假设。请确认。

在我遇到同样的问题并毁掉我 1 天的时间来寻找解决方案之前的某个时候。根据我的经验,我在下面列出了开发人员在将 Dagger2 与 android kotlin 集成时必须考虑的几点。

  1. ComponentModule class 中使用的范围必须相同。
  2. apply plugin: 'kotlin-kapt 必须在您的 build.gradle 文件中,否则您将无法生成 DaggerComponent class.

希望对一些开发者有所帮助。