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

如何在下拉刷新时重新触发Kotlin Flow获取数据?

解决方案

核心思路是通过触发流控制数据重新加载,结合flatMapLatest操作符,每次触发时重新执行用例并返回新数据流。

修改后的ViewModel代码

class MyViewModel(
    private val getSomeDataUsecase: GetSomeDataUseCase
) : ViewModel() {
    // 触发刷新的信号流,无初始值,每次发送事件触发重新加载
    private val refreshTrigger = MutableSharedFlow<Unit>(replay = 0)

    // 组合触发流与数据请求流,初始自动触发一次加载,后续随刷新事件重新请求
    val myData: Flow<SomeData> = refreshTrigger
        .onStart { emit(Unit) }
        .flatMapLatest {
            getSomeDataUsecase()
        }

    fun refreshData() {
        viewModelScope.launch {
            refreshTrigger.emit(Unit)
        }
    }
}

关键逻辑说明

  • refreshTrigger:用MutableSharedFlow<Unit>作为刷新信号载体,replay = 0确保不会留存旧事件,每次调用refreshData时发送新的触发信号。
  • onStart { emit(Unit) }:保证ViewModel初始化时自动执行首次数据加载,无需手动调用刷新方法。
  • flatMapLatest:新触发事件到来时,自动取消未完成的旧请求,确保UI始终接收最新请求结果,避免旧数据覆盖新数据的问题。

带刷新状态的扩展方案

如果需要在UI层控制下拉刷新动画的显示/隐藏,可以结合状态流管理加载状态:

class MyViewModel(
    private val getSomeDataUsecase: GetSomeDataUseCase
) : ViewModel() {
    private val _isRefreshing = MutableStateFlow(false)
    val isRefreshing: StateFlow<Boolean> = _isRefreshing

    private val refreshTrigger = MutableSharedFlow<Unit>(replay = 0)

    val myData: Flow<SomeData> = refreshTrigger
        .onStart { emit(Unit) }
        .flatMapLatest {
            flow {
                _isRefreshing.value = true
                try {
                    emit(getSomeDataUsecase().first())
                } finally {
                    _isRefreshing.value = false
                }
            }
        }

    fun refreshData() {
        viewModelScope.launch {
            refreshTrigger.emit(Unit)
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:54:59