如何在 Compose 上使用 android room (Kotlin) 返回新插入的项目(行)ID?

How to return newly inserted item(row) id using android room (Kotlin) on Compose?

提问人:user924223 提问时间:11/10/2023 最后编辑:user924223 更新时间:11/12/2023 访问量:49

问:

我需要获取添加到 ROOM 数据库表的记录的自动生成的 ID。

为了回答我的问题,我找到了以下答案:文本

但就我而言,这不是一个解决方案,因为在 Compose 中我不能使用代码:lifecycleScope.launch

//DAO
@Insert
suspend fun addwarrantyget(warrantyEntity: WarrantyEntity): Long

//Repository
suspend fun addwarrantyget(warrantyEntity: WarrantyEntity):Long {
        return inventoryDB.warrantyDao().addwarrantyget(warrantyEntity)
    }

//viewModel
fun addwarrantyget(warranty: WarrantyEntity) =
        viewModelScope.launch {
            repository.addwarrantyget(warranty)
        }

//Inside Compose Fun
lifecycleScope.launch {
    val id = viewModel.addwarrantyget(warranty)
    Log.i("INSERT_ID", "Inserted ID is: $id")
}

根据建议和我的理解:

我补充道:

视图模型

private val _newItemId = MutableStateFlow(-1L)
val newItemId: StateFlow<Long> = _newItemId

fun addwarrantyget(warranty: WarrantyEntity) = viewModelScope.launch {
    val newId = repository.addwarrantyget(warranty)
    _newItemId.emit(newId!!)
}

Compose 函数提取

Button(
                onClick = {

                    viewModel.addwarrantyget(
                       WarrantyEntity(
                            0,
                           null,
                            insn,
                            indescription,
                            null,
                           instartdateP.value,
                           inenddateP.value,
                           inprovider,
                           instartdateM.value,
                           inenddateM.value,
                           inmanufacturer
                        )
                    )
                    val newItemID by viewModel.newItemId.collectAsStateWithLifecycle()
                    LaunchedEffect(newItemID) {
                        if (newItemID == -1L) return@LaunchedEffect
                        // Do what you need with the new id here
                        warrantyId.value = viewModel.newItemId
                        mToast("Warranty Added", mContext)
                    }

                    mToast("Warranty Added", mContext)

                },
                colors = ButtonDefaults.buttonColors(Color.Blue)

            ) {
                Text(text = "Add Warranty")
            }

collectAsStateWithLifecycle:给出未定义的引用错误

warrantyId.value = viewModel.newItemId:出现“需要长时间查找 StateFlow”错误

LaunchedEffect:给出@Composable调用只能从上下文中发生......

Kotlin 插入 android-jetpack-compose android-room 返回值

评论


答:

1赞 JanItor 11/10/2023 #1

在 compose 中,你有 LaunchedEffect。您不会在调用的同一位置获取 id,但您可以从 as 状态中使用新的 id 值。viewModel.addwarrantyget(warranty)viewModel

视图模型

private val _newItemId = MutableStateFlow(-1)
val newItemId: StateFlow<Int> = _newItemId

fun addwarrantyget(warranty: WarrantyEntity) = viewModelScope.launch {
    val newId = repository.addwarrantyget(warranty)
    _newItemId.emit(newId)
}

可组合

    val newItemID by viewModel.newItemId.collectAsStateWithLifecycle()
    LaunchedEffect(newItemID) {
        if (newItemID == -1) return@LaunchedEffect
        // Do what you need with the new id here
    }

请注意,我设置了过滤掉默认值,当然还有其他方法可以做到这一点。newItemID-1

编辑:

关于错误。已经包含新 id 的值,您无需再次读取它。Require Long Found StateFlownewItemIDviewModel

mToast("New id: $newItemID", mContext)

请阅读有关国家的信息,以更好地了解这里正在发生的事情。

关于错误。正如错误所说,(作为可组合函数)不能从 lambda 调用,这不是可组合函数。请务必了解,使用状态和调用并不绑定在一起。您可以改为将 放入可组合屏幕级别。@Composable invocations can only happen from the context...LaunchedEffectonClicknewItemIdviewModel.addwarrantyget()LaunchedEffect

@Composable
fun YourScreen(
    viewModel: YourViewModel = viewModel()
) {
    // other code
    val newItemID by viewModel.newItemId.collectAsStateWithLifecycle()
    LaunchedEffect(newItemID) {
        if (newItemID == -1) return@LaunchedEffect
        mToast("New id: $newItemID", mContext)
    }
    // other composables
}

评论

0赞 user924223 11/12/2023
如何添加回复?在此评论部分中,我无法添加我添加的代码所遇到的错误。
0赞 JanItor 11/12/2023
@user924223 您可以编辑问题。
0赞 user924223 11/12/2023
还行。我编辑了问题,根据所做的更改添加了更多信息。
0赞 user924223 11/13/2023
我为 collectAsStateWithLifecycle() 添加了依赖项“implementation ”androidx.lifecycle:lifecycle-runtime-compose:2.6.2”。但是我仍然不知道我应该在哪里调用 LaunchEffect,因为我需要它依赖于 Click 事件,因为它必须仅在@Insert之后运行,然后添加记录。
0赞 JanItor 11/13/2023
@user924223我不明白你想做什么,你能详细说明一下你到底想要这个ID做什么吗?