【问题标题】:How to get first element from a Room DB flow?如何从 Room DB 流中获取第一个元素?
【发布时间】:2023-03-17 12:21:02
【问题描述】:

我的存储库中有这样的功能

fun getSelfReportMetaById(cardId: String): Flow<SelfReportMeta?> {
        return selfReportMetaDao.getById(cardId)
                .map { it.map { entity -> entity.toSelfReportMeta() } }
                .map {
                    it.firstOrNull()
                }
    }

我们的想法是从我的数据库中获取一个独特的字段。我不希望每个 cardId 有多个元素。

在我的 viewModel 中,我想检查数据库以查看密钥是否已存在。如果它不存在,我们将创建一个新的。如果存在,我们将获取它,更新它,然后将其插入回数据库中。

userRepository.getSelfReportMetaById(cardId)
                    .onEach { userCard ->
                        if (userCard == null) {
                            userRepository.insertSelfReportMeta(createNewSelfReportMeta(cardId))
                        } else {
                            userRepository.insertSelfReportMeta(updateSelfReportMeta(userCard))
                        }
                    }.launchIn(viewModelScope)

有什么问题?问题是当这个函数运行时,else{} 块将基本上连续运行,直到我进入下一个视图。我知道这一点是因为 updateSelfReportMeta() 有一个递增操作(++),并且整数值不断上升。我只希望它发生一次。

【问题讨论】:

  • 您可以考虑让suspend fun getSelfReportMetaById(cardId: String): SelfReportMeta?返回单个值,而不是返回可空值的流

标签: kotlin android-room coroutine


【解决方案1】:

您可以使用suspending function first 获取流发出的第一个值,然后终止流。

你的代码会变成类似

viewModelScope.launch {
    val userCard = userRepository.getSelfReportMetaById(cardId).first()
    if (userCard == null) {
        userRepository.insertSelfReportMeta(createNewSelfReportMeta(cardId))
    } else {
        userRepository.insertSelfReportMeta(updateSelfReportMeta(userCard))
    }
}

【讨论】:

    猜你喜欢
    • 2020-12-03
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 2021-12-08
    • 2016-03-20
    • 2015-11-22
    • 1970-01-01
    • 2012-12-08
    相关资源
    最近更新 更多