我正在 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")
}
当调用函数将绑定的文本数据添加到任务对象并将其存储到数据库中时,程序崩溃并生成上述错误。
根据评论,您的代码(至少数据库代码)没有问题。所以问题很可能出在 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
}
使用的模块构建等级:-
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 更改为 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 设置:-