Android Room Persistence 库和 Kotlin

Posted

技术标签:

【中文标题】Android Room Persistence 库和 Kotlin【英文标题】:Android Room Persistence library and Kotlin 【发布时间】:2017-10-19 07:23:20 【问题描述】:

我正在尝试使用 Kotlin 和 Room Persistence Library 编写一个简单的应用程序。 我在 android Persistence 代码实验室中关注了the tutorial。

这是我在 Kotlin 中的 AppDatabase 课程:

@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() 
    abstract fun userModel(): UserDao

    companion object 
        private var INSTANCE: AppDatabase? = null
        @JvmStatic fun getInMemoryDatabase(context: Context): AppDatabase 
            if (INSTANCE == null) 
                INSTANCE = Room.inMemoryDatabaseBuilder(context.applicationContext, AppDatabase::class.java).allowMainThreadQueries().build()
            
            return INSTANCE!!
        

        @JvmStatic fun destroyInstance() 
            INSTANCE = null
        
    

但是当我尝试运行该应用程序时,它立即崩溃。 这是崩溃日志:

Caused by: java.lang.RuntimeException: cannot find implementation for com.ttp.kotlin.kotlinsample.room.AppDatabase. AppDatabase_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.ttp.kotlin.kotlinsample.room.AppDatabase$Companion.getInMemoryDatabase(AppDatabase.kt:19)
    at com.ttp.kotlin.kotlinsample.MainKotlinActivity.onCreate(MainKotlinActivity.kt:28)
    at android.app.Activity.performCreate(Activity.java:6272)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494) 
    at android.app.ActivityThread.access$900(ActivityThread.java:157) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)

看起来AppDatabase_Impl 类不是自动生成的。我检查了从codelab下载的原始java应用程序,发现AppDatabase_Impl是自动生成的。

Kotlin 版本:1.1.2-3 房间版:1.0.0-alpha1

有没有人有这方面的经验?

编辑: 使用kapt 解决了我的问题。就我而言,我必须将annotationProcessor 替换为kapt

【问题讨论】:

你也可以发布你的 build.gradle 吗? 你的模块 build.gradle 中有 apply plugin: 'kotlin-kapt'kapt "android.arch.persistence.room:compiler:1.0.0-alpha1" 吗? 谢谢。使用 kapt 插件解决了我的问题。 @ThanhPham 我也有同样的问题,但是添加 kapt 会引入一些 gradle 错误,请看这里***.com/questions/44142964/…。你能提供你的 gradle 文件吗? @chandil03 我看到你只是添加了 kapt。就我而言,我必须用 kapt 替换 annotationProcessor。 【参考方案1】:

通常在项目build.gradle我定义依赖版本:

ext 
    buildToolsVersion = '25.0.2'
    supportLibVersion = '25.3.1'
    espressoVersion = '2.2.2'
    archRoomVersion = '1.0.0-alpha1'

所以在应用程序build.gradle 中,依赖项看起来像:

dependencies 
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

    compile "com.android.support:appcompat-v7:$rootProject.supportLibVersion"

    compile "android.arch.persistence.room:runtime:$rootProject.archRoomVersion"
    annotationProcessor "android.arch.persistence.room:compiler:$rootProject.archRoomVersion"
    kapt "android.arch.persistence.room:compiler:$rootProject.archRoomVersion"

    androidTestCompile("com.android.support.test.espresso:espresso-core:$rootProject.espressoVersion", 
        exclude group: 'com.android.support', module: 'support-annotations'
    )
    testCompile 'junit:junit:4.12'

现在您可以在 Kotlin 中定义实体 Daos 和数据库。

数据库:

@Database(entities = arrayOf(User::class), version = 1)
abstract class Database : RoomDatabase() 
    abstract fun userDao(): UserDao

实体:

@Entity(tableName = "user")
class User 
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0
    var name: String = ""

道:

@Dao
interface UserDao 
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)

注意:使用参数查询。 Kotlin 重命名参数,因此通过 userId 检索属于用户的所有电子邮件的 SQL 查询是:

@Query("SELECT * FROM email "
            + "INNER JOIN user ON user.id = email.userId "
            + "WHERE user.id = :arg0")
    fun getEmailsForUser(userId: Int): List<Email>

【讨论】:

感谢您的帮助。就我而言,Kotlin 将参数重命名为 p0, p1... 而不是 arg0, arg1... @Nicola De Fiorenze 我也有同样的问题,但添加 kapt 会引入一些 gradle 错误,请查看***.com/questions/44142964/…。 如何拨打db.userDao().insertAll(user) 在另一个答案中提到的build.gradle文件中也需要apply plugin: 'kotlin-kapt'【参考方案2】:

在我的例子中,在 build.gradle 中,当你有“annotationProcessor”时,你需要用“kapt”进行复制,它可以工作。

compile "android.arch.persistence.room:runtime:$room_version"
annotationProcessor "android.arch.persistence.room:compiler:$room_version"
kapt "android.arch.persistence.room:compiler:$room_version"

【讨论】:

感谢您的帮助。 @Lyofen 我也有同样的问题,但是添加 kapt 会引入一些 gradle 错误,请看这里***.com/questions/44142964/…。 非常感谢先生!【参考方案3】:

试试这些步骤

第 1 步。project.gradle 文件中设置room_version

buildscript 
    ext.kotlin_version = '1.1.51'
    ext.room_version = '1.0.0-alpha9-1'
...

第 2 步。app.gradle 文件中应用 kotlin-kapt 插件,这解决了我的问题。

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

android 
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
...

第 3 步。app.gradle 文件中添加 kapt 依赖项

dependencies 
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "android.arch.persistence.room:runtime:$room_version"
    annotationProcessor "android.arch.persistence.room:compiler:$room_version"
    kapt "android.arch.persistence.room:compiler:$room_version"
...

【讨论】:

【参考方案4】:

任何有兴趣将 Kotlin 与 Room 和数据绑定一起使用的人都可以查看此示例项目 https://github.com/entrpn/kotlin-room-databinding

【讨论】:

【参考方案5】:

我几乎放弃了。但是按照 dharmin007 所说的去做之后,我还必须清理该项目。这使它工作。我注意到,每当您将 kapt 添加到 gradle 时,您必须在同步 gradle 后清理项目。

【讨论】:

【参考方案6】:

我不知道我的答案是否有必要我知道上面的一些答案已经包含在他们的答案中,但他们添加了其他内容

仅添加 apply plugin: 'kotlin-kapt'

【讨论】:

以上是关于Android Room Persistence 库和 Kotlin的主要内容,如果未能解决你的问题,请参考以下文章

从 SQLite 迁移到 Android Room Persistence Library

Android Persistence room:“无法弄清楚如何从光标读取此字段”

如何使用 Android Room Persistence Library 将 Column 注释为 NOT NULL

Android Room框架学习笔记

Android Room Persistence Library - 如何查找 ID 列表中包含 ID 的实体?

Android Room 数据库 DAO 调试日志