【问题标题】:Room Persistence lib implementation in Kotlin(Gradle error)Kotlin 中的 Room Persistence lib 实现(Gradle 错误)
【发布时间】:2017-10-24 13:52:23
【问题描述】:

我正在 kotlin 中为我的数据库实现实现 Room 持久性库。 在Android Room Persistences library and Kotlin 线程中提出了同样的问题,应用这些解决方案会导致不同的 gradle 错误:

以下是我的Entity、Dao 和Database 课程:

Food.kt

@Entity
class Food(@ColumnInfo(name = "food_name") var foodName: String,
           @ColumnInfo(name = "food_desc") var foodDesc: String,
           @ColumnInfo(name = "protein") var protein: Double,
           @ColumnInfo(name = "carbs") var carbs: Double,
           @ColumnInfo(name = "fat") var fat: Double)
{
    @ColumnInfo(name = "id")
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0
    @ColumnInfo(name = "calories")
    var calories: Double = 0.toDouble()
}

PersonalizedFood.kt

@Entity(primaryKeys = arrayOf("food_id","date"))
class PersonalizedFood(@ColumnInfo(name = "quantity") var quantity: Int,
                       @ColumnInfo(name = "unit") var unit: String,
                       @ColumnInfo(name = "date") var date: Date){

    @ColumnInfo(name = "food_id")
    var foodId:Long = 0
}

FoodDao.kt

@Dao
interface FoodDao {

    companion object{
        const val ID = "id"
        const val NAME = "name"
        const val PROTEIN = "protein"
        const val DESC = "desc"
        const val CARBS = "carbs"
        const val FAT = "fat"

        const val DATE = "date"
        const val FOOD_ID = "food_id"

        const val ALL_FOOD_LIST = "food"
        const val PERSONALISED_FOOD_LIST = "personalised_food"
    }

    /**
     * Returns food details of a food given by food_id
     */
    @Query("SELECT * FROM $ALL_FOOD_LIST WHERE $ID=:food_id")
    fun getFoodDetails(food_id:Long):Food

    /**
     * Inserts food items in all_food_list
     */
    @Insert
    fun addFoodList(list:ArrayList<Food>)

    @Insert(onConflict = REPLACE)
    fun saveFood(food:PersonalizedFood)

    @Query("SELECT * FROM $PERSONALISED_FOOD_LIST WHERE $FOOD_ID=:foodId and $DATE=:date")
    fun getFood(foodId:Int, data:Date):PersonalizedFood

    @Query("SELECT * FROM $ALL_FOOD_LIST where $ID in (select $FOOD_ID from $PERSONALISED_FOOD_LIST where $DATE = :date)")
    fun getFood(date:Date):ArrayList<Food>
}

Converter.kt

class Converter {

    companion object{
        @TypeConverter
        fun fromTimestamp(value: Long?): Date? {
            return if (value == null) null else Date(value)
        }

        @TypeConverter
        fun dateToTimestamp(date: Date): Long {
            return date.time
        }
    }
}

FoodDatabase.kt

@Database(entities = arrayOf(Food::class, PersonalizedFood::class), version = 1)
@TypeConverters(Converter::class)
abstract class FoodDatabase : RoomDatabase(){
    abstract fun foodDao():FoodDao

    companion object{
        private val databaseName = "diet"

        var dbInstance:FoodDao? = null
        fun getInstance(context:Context):FoodDao?{
            if(dbInstance == null)
                dbInstance = Room.inMemoryDatabaseBuilder(context, FoodDatabase::class.java).build().foodDao()
            return dbInstance;
        }
    }
}

当我运行以下代码来创建数据库时:

FoodDatabase.getInstance(baseContext)?.getFood(Calendar.getInstance().time)

它给了我以下异常:

Caused by: java.lang.RuntimeException: cannot find implementation for com.chandilsachin.diettracker.database.FoodDatabase. FoodDatabase_Impl does not exist
                                                                                   at android.arch.persistence.room.Room.getGeneratedImplementation(Room.java:90)
                                                                                   at android.arch.persistence.room.RoomDatabase$Builder.build(RoomDatabase.java:340)
                                                                                   at com.chandilsachin.diettracker.database.FoodDatabase$Companion.getInstance(FoodDatabase.kt:21)
                                                                                   at com.chandilsachin.diettracker.MainActivity$SetUpFoodDatabase.doInBackground(MainActivity.kt:95)
                                                                                   at com.chandilsachin.diettracker.MainActivity$SetUpFoodDatabase.doInBackground(MainActivity.kt:77)
                                                                                   at android.os.AsyncTask$2.call(AsyncTask.java:295)
                                                                                   at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                                   at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
                                                                                   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                                                                                   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                                                                                   at java.lang.Thread.run(Thread.java:818) 

有人在 kotlin 中实现了房间持久化吗?

已编辑

我之前关于同一主题的问题被标记为与this 重复。虽然问题陈述相同,但给出的解决方案并不能解决我的问题。解决方案说我必须将替换 annotationProcessor 添加到 kapt "android.arch.persistence.room:compiler:1.0.0-alpha1" 依赖项。我进行了这些更改,但在项目构建时导致了 gradle 错误。

Information:Gradle tasks [:app:assembleDebug]
Warning:warning: Supported source version 'RELEASE_7' from annotation processor 'android.arch.persistence.room.RoomProcessor' less than -source '1.8'
Warning:warning: The following options were not recognized by any processor: '[kapt.kotlin.generated]'
/Users/BBI-M1025/Documents/BBI/Workspace_fun/Android/diet-tracker/app/src/main/java/com/chandilsachin/diettracker/database/Food.kt
Error:(1, 1) Some error(s) occurred while processing annotations. Please see the error messages above.
Error:Execution failed for task ':app:kaptDebugKotlin'.
> Compilation error. See log for more details
Information:BUILD FAILED in 10s
Information:2 errors
Information:2 warnings
Information:See complete output in console

我还附上了我的 gradle 文件:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.chandilsachin.diettracker"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    compile 'com.android.support:appcompat-v7:25.0.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha8'
    compile 'com.android.support:cardview-v7:25.0.1'
    compile 'com.android.support:recyclerview-v7:25.0.1'
    compile 'com.github.ne1c:rainbowmvp:1.2.1'
    compile "org.jetbrains.anko:anko-commons:0.10.0"

    /*annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
    compile "android.arch.lifecycle:extensions:1.0.0-alpha1"
    annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1"*/

    compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
    kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"

    testCompile 'junit:junit:4.12'
}
repositories {
    mavenCentral()
}

有人遇到过这个问题吗?

【问题讨论】:

  • 版主,请在标记为重复之前检查问题陈述。
  • 您可以跟踪一些问题youtrack.jetbrains.com/issues/KT,如果您认为相关,也可以提交一些错误。
  • 你能检查两件事吗? 1. Kotlin to JVM targhet 版本(文件> 设置> Kotlin 编译器) 2. 项目JDK 版本文件> 项目结构> “JDK 位置”查看为您的项目设置的JDK;然后转到设置的路径,导航到“bin”,然后输入“java -version”
  • @NicolaDeFiorenze JVM目标版本为1.6,java版本为“1.8.0_91”。
  • @chandil03 尝试更新 JDK,可能更新到 v1.8.0_121。我尝试将 Kotlin 的 JVM 目标设置为 1.6 和 1.8,但无法重现您的错误。 java版本似乎是唯一的区别

标签: android kotlin


【解决方案1】:

在为这个问题转了一圈之后,我想到了解决方案。

这真的很难,因为目前还没有官方教程、博客等来帮助解决这个问题。

我必须对 gradle 插件和依赖项的所有组合进行多次测试和试验,因为我知道只有 gradle config 有问题。

让我们来解决:

我不得不从 build.gradle(:module) 文件中删除 apply plugin: 'kotlin-kapt' 并将annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1" 替换为kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"。

这是成功编译代码的gradle配置。

但是还有更多的事情需要检查。您必须初始化@Entity class 的属性,这与Room Persistence lib doc 中给出的java 不同。虽然有getter setter,但没有提到创建带有初始化的构造函数。 所以我不得不用这个来改变我的@Entity类:

@Entity(tableName = "all_food_list")
class Food (@ColumnInfo(name = "food_name") var foodName: String = "",
            @ColumnInfo(name = "food_desc") var foodDesc: String = "",
            @ColumnInfo(name = "protein") var protein: Double = 0.0,
            @ColumnInfo(name = "carbs") var carbs: Double = 0.0,
            @ColumnInfo(name = "fat") var fat: Double = 0.0,
            @ColumnInfo(name = "calories") var calories: Double = 0.0)
{
    @ColumnInfo(name = "id")
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0
}

现在对于 TypeConverts,与 java 不同,您需要创建普通函数而不是静态函数(伴生对象):

class Converters{

        @TypeConverter
        fun fromTimestamp(value: String): Calendar {
            val arr = value.split("-")
            val cal = Calendar.getInstance()
            cal.set(arr[0].toInt(), arr[1].toInt(), arr[2].toInt())
            return cal
        }

        @TypeConverter
        fun dateToTimestamp(date: Calendar): String {
            return "${date.get(Calendar.DATE)}-${date.get(Calendar.MONTH)+1}-${date.get(Calendar.YEAR)}"
        }

}

我正在添加 build.gradle 文件以使其更清晰:

build.gradle(:project)

buildscript {
    ext.kotlin_version = '1.1.2-4'
    ext.gradle_version_stable = '2.3.2'
    ext.gradle_version_preview = '3.0.0-alpha1'
    ext.anko_version = '0.10.0'
    repositories {
        maven { url 'https://maven.google.com' }
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha1'
        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 {
        maven { url 'https://maven.google.com' }
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

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

build.gradle(:module)

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.chandilsachin.diettracker"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    ...
    ...
    // room persistence dependency 
    compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
    kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"

    testCompile 'junit:junit:4.12'
}
repositories {
    mavenCentral()
}

我想这就是全部,我这样做是为了让我的代码工作起来。

希望这对其他人也有帮助。

【讨论】:

  • 您也可以将转换器保留为object,但将@JvmStatic 放在方法上。这样生成的方法实际上是静态的,Room 插件会很高兴,
  • 向属性添加 default 值可以解决我的问题。这是可怕的解决方案。我什至认为这是一个错误。
  • @murt 这不是一个错误,因为实体类不需要有参数化的构造函数,它必须有默认值。
  • 好的,但是Java中的字段可能没有初始化,那么为什么var属性必须呢?
【解决方案2】:

man 只需在 build.gradle 中添加以下内容。以上依赖:D

    kapt {
          generateStubs = true
    }

【讨论】:

  • 这并不能解决没有生成 Impl 文件的问题——至少对我来说没有。
猜你喜欢
  • 2017-10-23
  • 2017-10-19
  • 1970-01-01
  • 2018-12-14
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
  • 2017-11-15
  • 1970-01-01
相关资源
最近更新 更多