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

如何在Jetpack Compose按钮中捕获Room操作的SQLiteException

解决Jetpack Compose中Room唯一约束插入的SQLiteException捕获问题

问题根源

当前代码里,ViewModel的addfloor函数通过viewModelScope.launch启动了独立协程,该协程的异常会被viewModelScope默认的异常处理器拦截,无法传递到Composable按钮点击事件的try-catch块中;再加上全局异常捕获模块的拦截,导致你无法在目标位置捕获SQLiteException。

解决方案步骤

1. 将ViewModel中的插入方法改为挂起函数

移除ViewModel内部的协程启动,让函数直接挂起,使异常能向上传递到调用方:

class InventoryViewModel(val repository: InventoryRepository): ViewModel() {

    // 改为挂起函数,不再内部启动协程
    suspend fun addfloor(floor: FloorEntity) {
        repository.addFloorToRoom(floor)
    }

    // 其他函数
}

2. 确保Repository和DAO的异常抛出逻辑正确

DAO层保留@Throws(SQLiteException::class)注解,确保插入冲突时抛出异常:

interface FloorDAO {
    @Insert(onConflict = OnConflictStrategy.ABORT )
    @Throws(SQLiteException::class)
    suspend fun addFloor(floorEntity: FloorEntity)

    // 其他DAO函数
}

Repository层直接调用DAO方法,无需额外处理:

class InventoryRepository (val inventoryDB: InventoryDB){

    suspend fun addFloorToRoom(floorEntity: FloorEntity){
        inventoryDB.floorDao().addFloor(floorEntity)
    }

    // 其他函数
}

3. 修改Composable按钮的点击事件逻辑

移除withContext(Dispatchers.IO)(Room的挂起函数默认已在IO线程执行),直接在协程中调用ViewModel的挂起函数并包裹try-catch:

Column(
    modifier = Modifier
        .padding(top = 22.dp, start = 6.dp, end = 6.dp)
        .fillMaxWidth(),
    horizontalAlignment = Alignment.CenterHorizontally
) {
    val coroutineScope = rememberCoroutineScope()

    Button(
        onClick = {
            coroutineScope.launch {
                try {
                    viewModel.addfloor(
                        FloorEntity(
                            0,
                            houseId!!.toLong(),
                            infloor,
                            "$location.$infloor"
                        )
                    )
                    mToast("Floor Added", mContext)
                } catch (e: SQLiteException) {
                    msgbox(
                        mContext,
                        e.message.toString(),
                        "Floor Could not be Added"
                    )
                }
            }
        },
        colors = ButtonDefaults.buttonColors(Color.Blue)
    ) {
        Text(text = "Add Floor in to House")
    }
}

4. 处理全局异常捕获的影响

如果全局异常捕获模块仍拦截该异常,需在全局处理器中添加判断:若异常是SQLiteException且来自Room插入逻辑,不拦截该异常,允许其向上传递到业务代码的try-catch中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 21:28:11