如何在下拉刷新时重新触发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
相关产品推荐
相关产品推荐

