You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中Room的insert方法加suspend关键字报错求解决方案

在Kotlin中为Room的insertConfCard方法添加suspend关键字时遭遇编译错误,求有效解决办法

错误信息

error: Type of the parameter must be a class annotated with @Entity or a collection/array of it.
    kotlin.coroutines.Continuation<? super java.lang.Long> continuation);
error: Not sure how to handle insert method's return type.
    public abstract java.lang.Object insertConfCard(@org.jetbrains.annotations.NotNull()
Execution failed for task ':app:kaptDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask$KaptExecutionWorkAction
   > java.lang.reflect.InvocationTargetException (no error message)

我的DAO代码

@Dao
interface ConfCardDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertConfCard(confCard: ConfCard): Long
}

生成的DAO代码

import java.lang.System;

@androidx.room.Dao()
@kotlin.Metadata(mv = {1, 7, 1}, k = 1, d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\t\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0002\bg\u0018\u00002\u00020\u0001J\u0019\u0010\u0002\u001a\u00020\u00032\u0006\u0010\u0004\u001a\u00020\u0005H\u00a7@\u00f8\u0001\u0000\u00a2\u0006\u0002\u0010\u0006\u0082\u0002\u0004\n\u0002\b\u0019\u00a8\u0006\u0007"}, d2 = {"Lcom/example/stid_settings_kotlin/datamodel/data/local/ConfCardDao;", "", "insertConfCard", "", "confCard", "Lcom/example/stid_settings_kotlin/datamodel/data/local/ConfCard;", "(Lcom/example/stid_settings_kotlin/datamodel/data/local/ConfCard;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", "app_debug"})
public abstract interface ConfCardDao {
    
    @org.jetbrains.annotations.Nullable()
    @androidx.room.Insert(onConflict = androidx.room.OnConflictStrategy.REPLACE)
    public abstract java.lang.Object insertConfCard(@org.jetbrains.annotations.NotNull()
    com.example.stid_settings_kotlin.datamodel.data.local.ConfCard confCard, @org.jetbrains.annotations.NotNull()
    kotlin.coroutines.Continuation<? super java.lang.Long> continuation);
}

app模块build.gradle依赖配置

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.5.1'
    implementation 'com.google.android.material:material:1.7.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    // Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
//    implementation "com.squareup.okhttp3:okhttp:4.9.0"

    // Coroutines
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'

    // Coroutine Lifecycle Scopes
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"

    // Room
    implementation "androidx.room:room-runtime:2.3.0"
    kapt "androidx.room:room-compiler:2.3.0"

    // optional - Kotlin Extensions and Coroutines support for Room -- use room with coroutine
    implementation "androidx.room:room-ktx:2.3.0"
}

项目根目录build.gradle

plugins {
    id 'com.android.application' version '7.2.0' apply false
    id 'com.android.library' version '7.2.0' apply false
    id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}

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

实体类ConfCard代码

@Entity(tableName = "confcard", indices = [Index(value = ["confName"], unique = true)])
class ConfCard {

    @PrimaryKey(autoGenerate = true)
    var id: Int = 0

    @NotNull
    var confName: String

    @NotNull
    var name: String

    @NotNull
    var pid: String

    @NotNull
    var pver: String

    @NotNull
    var data: String

    @NotNull
    var kNew: String

    @NotNull
    var kCur: String

    @NotNull
    var uuid: String

    @NotNull
    var type: String // ScbvsOCB

    @NotNull
    var tkNeeded: String

    @NotNull
    var originatingServer: String

    constructor() {
        this.id = 0
        this.confName = ""
        this.name = ""
        this.pid = ""
        this.pver = ""
        this.data = ""
        this.kNew = ""
        this.kCur = ""
        this.uuid = ""
        this.type = ""
        this.originatingServer = ""
        this.tkNeeded = ""
    }
    
    constructor(
        ConfName: String,
        Name: String,
        PartId: String,
        PartVer: String,
        Data: String,
        KNew: String,
        KCur: String,
        UUID: String,
        CardType: String,
        OriginatingServer: String,
        TkNeeded: String,
    ) {
        this.confName = ConfName
        this.name = Name
        this.pid = PartId
        this.pver = PartVer
        this.data = Data
        this.kNew = KNew
        this.kCur = KCur
        this.uuid = UUID
        this.type = CardType
        this.originatingServer = OriginatingServer
        this.tkNeeded = TkNeeded
    }

    @JvmName("getId1")
    fun getId(): Int = id

    @JvmName("setId1")
    fun setId(id: Int) {
        this.id = id
    }

    @JvmName("getConfName1")
    fun getConfName(): String = confName

    @JvmName("setConfName1")
    fun setConfName(confName: String) {
        this.confName = confName
    }

    @JvmName("getName1")
    fun getName(): String = name

    @JvmName("setName1")
    fun setName(name: String) {
        this.name = name
    }

    fun getPartId(): String = pid

    fun setPartId(pid: String) {
        this.pid = pid
    }

    fun getPartVer(): String = pver

    fun getPartVer(pver: String) {
        this.pver = pver
    }

    @JvmName("getData1")
    fun getData(): String = data

    @JvmName("setData1")
    fun setData(data: String) {
        this.data = data
    }

    @JvmName("getKNew1")
    fun getKNew(): String = kNew

    @JvmName("setKNew1")
    fun setKNew(kNew: String) {
        this.kNew = kNew
    }

    @JvmName("getKCur1")
    fun getKCur(): String = kCur

    @JvmName("setKCur1")
    fun setKCur(kCur: String) {
        this.kCur = kCur
    }

    fun getUUID(): String = uuid

    fun setUUID(uuid: String) {
        this.uuid = uuid
    }

    fun getCardType(): String = type

    fun setCardType(type: String) {
        this.type = type
    }

    @JvmName("getOriginatingServer1")
    fun getOriginatingServer(): String = originatingServer

    @JvmName("setOriginatingServer1")
    fun setOriginatingServer(originatingServer: String) {
        this.originatingServer = originatingServer
    }

    @JvmName("getTkNeeded1")
    fun getTkNeeded(): String = tkNeeded

    @JvmName("setTkNeeded1")
    fun setTkNeeded(tkNeeded: String) {
        this.tkNeeded = tkNeeded
    }
}

解决办法

1. 修复实体类中的方法错误

实体类ConfCard里的getPartVer方法存在定义错误,把原本的setter写成了getter,导致Room无法正确解析实体字段:

// 错误写法
fun getPartVer(pver: String) {
    this.pver = pver
}

// 改为正确的setter
fun setPartVer(pver: String) {
    this.pver = pver
}

2. 升级Room版本以兼容Kotlin版本

当前使用的Room 2.3.0与Kotlin 1.7.10版本不兼容,Room从2.4.0开始才更好地支持Kotlin 1.6+版本。建议将Room相关依赖升级到稳定兼容版本,比如2.5.0:

// Room
implementation "androidx.room:room-runtime:2.5.0"
kapt "androidx.room:room-compiler:2.5.0"
implementation "androidx.room:room-ktx:2.5.0"

3. 正确添加suspend关键字到DAO方法

修改DAO代码,在方法前添加suspend关键字,Room的ktx扩展会自动处理协程逻辑:

@Dao
interface ConfCardDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertConfCard(confCard: ConfCard): Long
}

4. 清理并重新构建项目

执行Android Studio中的Clean Project,然后Rebuild Project,清除kapt生成的旧代码缓存,避免残留代码导致编译错误。


内容的提问来源于stack exchange,提问作者Ahmer Iqbal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 05:15:31