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

使用NetworkBoundResource时重复搜索同关键词协程始终活跃如何解决

问题根因

核心原因是 Room 返回的查询 Flow 是无限观察流:

  • Room 针对表查询返回的 Flow 只要处于被收集状态,就会持续监听对应表的数据变更,只要数据发生更新就会发射新值,永远不会主动结束。
  • 你实现的 networkBoundResource 最后通过 emitAll(flow) 把 Room 对应的无限 Flow 暴露给上层,ViewModel 层收集这个流的协程(也就是 searchJob 对应的协程)会一直处于挂起等待新值的状态,所以 searchJob.isActive 永远返回 true,触发重复搜索拦截逻辑。
解决方案

根据你的业务需求选择以下任意一种方案即可:

方案1:搜索场景不需要实时监听数据库变化,仅需单次搜索结果

在流的末端追加 take 操作符,拿到目标结果后主动结束流,让协程正常终止:

override fun searchPodcasts(term: String) = networkBoundResource(
    // 原有逻辑保持不变
).flowOn(ioDispatcher)
// 走网络请求会先后发射 Loading、Success/Error 两个事件,take(2) 拿到结果后立即结束流
.take(2)

如果你的业务不需要 Loading 状态,也可以替换为 take(1),仅取最终结果就结束流。

方案2:需要保持数据库变更实时同步,搜索页要随数据库更新自动刷新

这种场景下流需要长期保持活跃,不能强制结束,需要修改重复搜索的拦截逻辑:
新增变量标记上一次搜索的完成状态,不再仅依靠 searchJob.isActive 判断是否拦截:

// ViewModel 新增变量,记录上一次成功完成搜索的关键词
private var lastFinishedQuery: String? = null

fun onSearchPodcast(term: String) {
    // 仅当同关键词、且上一次同关键词搜索还未拿到结果时才拦截
    if (term == query && lastFinishedQuery != term && searchJob?.isActive == true) return

    query = term
    lastFinishedQuery = null
    _searchPodcasts.value = emptyList()
    showLive()

    searchJob?.cancel()
    searchJob = viewModelScope.launch {
        itunesRepo.searchPodcasts(term).collect { result ->
            Timber.d("Mtali : $result")
            when(result) {
                is Resource.Loading -> {
                    spinner(true)
                    if (!result.data.isNullOrEmpty()) {
                        _searchPodcasts.value = result.data.toIPodcasts()
                    }
                }
                is Resource.Error -> {
                    // 标记本次搜索已结束
                    lastFinishedQuery = term
                    message(result.error?.message)
                    spinner(false)
                }
                is Resource.Success -> {
                    // 标记本次搜索已结束
                    lastFinishedQuery = term
                    if (result.data.isNullOrEmpty()) {
                        message("Empty response")
                    } else {
                        _searchPodcasts.value = result.data.toIPodcasts()
                    }
                    spinner(false)
                }
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 19:48:02