Android Room 未生成正确的具体 Database_Ipml 类

问题描述 投票:0回答:1

我正在 Android Studio 中使用 Jetpack:Room 作为数据库构建一个待办事项列表应用程序。我已按照 Android 开发人员教程对我的代码进行建模,但是当我尝试调用时,出现错误“java.lang.RuntimeException:无法找到 com.example.todolist.database.TaskRoomDatabase 的实现。TaskRoomDatabase_Impl 不存在”首次插入功能并创建数据库。我使用 Room 版本 2.5.2、用于“room-compiler”的 ksp 和用于 java 的版本 1_8,以及用于导航的 2.7.3。

这是task.kt类:

@Entity(tableName = "tasks")
data class Task(
    @PrimaryKey(autoGenerate = true)  val id: Int = 0,
    @ColumnInfo(name = "task_name") val taskName: String,
    @ColumnInfo(name = "task_description") val taskDescription: String
){}

TaskDao.kt 类:

//Database Access Object to the Task entity database
@Dao
interface TaskDao {

    @Query("SELECT * from tasks WHERE task_name = :name")
    fun getTask(name: String): List<Task>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(task: Task) : Long

    @Update
    suspend fun update(task: Task)

    @Delete
    suspend fun delete(task: Task)
}

TaskRoomDatabase.kt

@Database(entities = [Task::class], version = 1, exportSchema = false)
abstract class TaskRoomDatabase : RoomDatabase() {

    abstract fun taskDao(): TaskDao

    companion object{
        @Volatile
        private var INSTANCE: TaskRoomDatabase? = null

        fun getDatabase(context: Context): TaskRoomDatabase {
            //if INSTANCE is not null, return it
            //else, create the database
            return INSTANCE ?: synchronized(this){
                val instance = Room.databaseBuilder(
                    context,
                    TaskRoomDatabase::class.java,
                    "task_database")
                    .createFromAsset("database/task_database")
                    .build()
                INSTANCE = instance

                instance
            }
        }
    }
}

以及片段中应该调用插入函数的函数。

private fun addNewTask() : Boolean {
        if (isEntryValid()) {
            viewModel.addTask(
                binding.editTaskTitle.text.toString(),
                binding.taskDetails.text.toString()
            )
            return true
        }
        val toast = Toast.makeText(context, "Invalid Input", Toast.LENGTH_SHORT)
        toast.show()
        return false
    }

//then the viewModel.addtask function referenced above
fun addTask(taskName: String, taskDescription: String){
        Log.d("TaskView", "passed strings: $taskName  , $taskDescription  ")
        val newTask = getNewTask(taskName, taskDescription)
        insertTask(newTask)
    }

    //Insert a task object to DB in non-blocking coroutine
    private fun insertTask(newTask: Task) {
        viewModelScope.launch {
        taskDao.insert(newTask)
        }
    }

我做错了什么?

编辑: 这是 build.gradle:

mport org.jetbrains.kotlin.storage.CacheResetOnProcessCanceled.enabled

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("com.google.devtools.ksp") apply true
}

android {
    namespace = "com.example.todolist"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.todolist"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    buildFeatures{
        viewBinding = true
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }

}

dependencies {
    val room_version = "2.5.2"
    implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
    implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")

    implementation ("androidx.room:room-ktx:$room_version")
    //kapt ("androidx.room:room-compiler:$room_version")

    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.9.0")
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    implementation ("com.google.android.material:material:<version>")
    implementation ("androidx.room:room-runtime:$room_version")
    annotationProcessor("androidx.room:room-compiler:$room_version")
    val nav_version = "2.7.3"
    implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
    implementation("androidx.navigation:navigation-ui-ktx:$nav_version")
    //Databinding to use DataBindingUtil
    implementation ("androidx.databinding:databinding-runtime:4.2.0")
    implementation("androidx.room:room-runtime:$room_version")
    annotationProcessor("androidx.room:room-compiler:$room_version")
    // To use Kotlin annotation processing tool (kapt)
    ksp("androidx.room:room-compiler:$room_version")
    // optional - Kotlin Extensions and Coroutines support for Room
    implementation("androidx.room:room-ktx:$room_version")
    // optional - RxJava2 support for Room
    implementation("androidx.room:room-rxjava2:$room_version")
    // optional - RxJava3 support for Room
    implementation("androidx.room:room-rxjava3:$room_version")
    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation("androidx.room:room-guava:$room_version")
    // optional - Test helpers
    testImplementation("androidx.room:room-testing:$room_version")
    // optional - Paging 3 Integration
    implementation("androidx.room:room-paging:$room_version")
}

当调用函数将绑定的文本数据添加到任务对象并将其存储到数据库中时,程序崩溃并生成上述错误。

android kotlin android-room android-jetpack android-jetpack-navigation
1个回答
0
投票

根据评论,您的代码(至少数据库代码)没有问题。所以问题很可能出在 ksp 上。

作为测试,获取您的代码,注释掉

.createFromAsset()
并包含
.allowMainThreadQueries
(用于轻松/简单的测试)。

最主要的是 java(生成)(根据 Android 视图)包含 TaskRoomDatabase_Impl,这是 kapt/ksp 构建的组件。

当运行一个非常基本的活动时,只需获取 db,然后将 dao 放入 Lateinits,然后使用任意字符串调用 getTask(没有数据,因此无关紧要)。这使得可以使用应用程序检查,显示:-

对于 ksp 使用的项目构建 gradle:-

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id 'com.android.application' version '7.2.1' apply false
    id 'com.android.library' version '7.2.1' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
  • 将 kotlin.android 增加到 1.8.0

使用的模块构建等级:-

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'com.google.devtools.ksp' version '1.8.0-1.0.8'
    //id 'kotlin-kapt'
}

android {
    compileSdk 33

    defaultConfig {
        applicationId "a.a.so77219401kotlinroomksp"
        minSdk 26
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.9.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.room:room-ktx:2.5.2'
    implementation 'androidx.room:room-runtime:2.5.2'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    ksp 'androidx.room:room-compiler:2.5.2'
}
  • (可以看出 kapt 之前被使用过(成功)但被注释掉了)
  • core-ktx 突出显示,版本较低,为 1.7.0,但它可以工作,1.9.0 可以工作,1.12.0 至少需要compileSDK 34(然后可以工作)。

如果从 kapt 更改为 ksp,我建议您执行清理,然后重建和编译。

用于测试的活动代码:-

class MainActivity : AppCompatActivity() {
    lateinit var db: TaskRoomDatabase
    lateinit var dao: TaskDao
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        db = TaskRoomDatabase.getDatabase(this)
        dao = db.taskDao()
        val x = dao.getTask("Blah")
    }
}
  • 允许应用程序停止/暂停并使用应用程序检查

用于测试的TaskRoomDatabase代码:-

@Database(entities = [Task::class], version = 1, exportSchema = false)
abstract class TaskRoomDatabase : RoomDatabase() {

    abstract fun taskDao(): TaskDao

    companion object{
        @Volatile
        private var INSTANCE: TaskRoomDatabase? = null

        fun getDatabase(context: Context): TaskRoomDatabase {
            //if INSTANCE is not null, return it
            //else, create the database
            return INSTANCE ?: synchronized(this){
                val instance = Room.databaseBuilder(
                    context,
                    TaskRoomDatabase::class.java,
                    "task_database")
                    //.createFromAsset("database/task_database")
                    .allowMainThreadQueries()
                    .build()
                INSTANCE = instance

                instance
            }
        }
    }
}

Android 视图 - 资源管理器看起来像:-

以防万一 gradle 设置:-

© www.soinside.com 2019 - 2024. All rights reserved.