Kotlin Android中Room数据库插入时suspend关键字引发错误
解决Room数据库插入数据的编译与运行时错误
编译错误信息
error: Type of the parameter must be a class annotated with @Entity or a collection/array of it.
kotlin.coroutines.Continuation<? super kotlin.Unit> continuation);
DAO代码
@Dao interface FavDishDao { @Insert fun insertFavDishDetails(favDish: FavDish) @Query("SELECT * FROM FAV_DISHES_TABLE ORDER BY ID") fun getAllDishesList(): Flow<List<FavDish>> }
相关build.gradle配置
模块级build.gradle
plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-kapt' } android { namespace 'pro.shivanshtariyal.recipeapp' compileSdk 33 defaultConfig { applicationId "pro.shivanshtariyal.recipeapp" minSdk 21 targetSdk 33 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 } packagingOptions{ exclude 'META-INF/atomicfu.kotlin_module' } kotlinOptions { jvmTarget = '1.8' } buildFeatures { viewBinding true } } dependencies { ... def room_version='2.2.6' implementation "androidx.room:room-ktx:$room_version" kapt "androidx.room:room-compiler:$room_version" implementation 'com.github.bumptech.glide:glide:4.12.0' implementation 'com.github.bumptech.glide:compiler:4.12.0' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' }
项目级build.gradle
plugins { id 'com.android.application' version '7.3.1' apply false id 'com.android.library' version '7.3.1' apply false id 'org.jetbrains.kotlin.android' version '1.8.0' apply false }
移除suspend关键字后的运行时错误
E/AndroidRuntime: FATAL EXCEPTION: main Process: pro.shivanshtariyal.recipeapp, PID: 5274 java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:267)
FavDish实体类代码
import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey @Entity(tableName = "fav_dishes_table") data class FavDish( @ColumnInfo val image: String, @ColumnInfo (name = "image_source") val imageSource: String, // Local or Online @ColumnInfo val title: String, @ColumnInfo val type: String, @ColumnInfo val category: String, @ColumnInfo val ingredients: String, // Specifies the name of the column in the table if you want it to be different from the name of the member variable. @ColumnInfo(name = "cooking_time") val cookingTime: String, @ColumnInfo(name = "instructions") val directionToCook: String, @ColumnInfo(name = "favorite_dish") var favoriteDish: Boolean = false, @PrimaryKey(autoGenerate = true) val id: Int = 0 )
解决方案
1. 修复编译错误
Room的@Insert方法若要配合协程使用,必须标记为suspend,否则编译器会抛出类型错误。修改DAO中的插入方法:
@Dao interface FavDishDao { @Insert suspend fun insertFavDishDetails(favDish: FavDish) @Query("SELECT * FROM FAV_DISHES_TABLE ORDER BY ID") fun getAllDishesList(): Flow<List<FavDish>> }
2. 解决主线程访问数据库问题
Room默认禁止在主线程执行数据库操作,避免阻塞UI,可通过以下两种方式处理:
方式一:用协程在后台线程执行
在ViewModel或Activity/Fragment中,使用官方提供的协程作用域启动后台任务:
// ViewModel中示例 class FavDishViewModel(private val dao: FavDishDao) : ViewModel() { fun insertDish(dish: FavDish) { viewModelScope.launch(Dispatchers.IO) { dao.insertFavDishDetails(dish) } } }
方式二(仅测试用):允许主线程访问
创建RoomDatabase实例时调用allowMainThreadQueries(),但此方法可能导致UI卡顿,不建议在生产环境使用:
@Database(entities = [FavDish::class], version = 1) abstract class FavDishDatabase : RoomDatabase() { abstract fun favDishDao(): FavDishDao companion object { fun getInstance(context: Context): FavDishDatabase { return Room.databaseBuilder(context, FavDishDatabase::class.java, "fav_dishes_db") .allowMainThreadQueries() .build() } } }
3. 升级Room版本(可选)
当前使用的Room 2.2.6版本较旧,建议升级到稳定新版本(如2.5.0+),避免版本兼容问题:
def room_version='2.5.0' implementation "androidx.room:room-ktx:$room_version" kapt "androidx.room:room-compiler:$room_version"
内容的提问来源于stack exchange,提问作者Shivansh Tariyal
相关产品推荐
相关产品推荐

