ViewModel中处理Supabase API响应及Flow与挂起函数选型
问题解答
一、处理ApiResponse.Loading和ApiResponse.Error状态
假设你的DayState是用于UI展示的状态类(包含加载状态、数据、错误信息等字段),在toDayState函数里可以按以下方式处理不同状态:
1. 处理Loading状态
当接收到ApiResponse.Loading时,核心是告诉UI当前处于加载状态:
- 将状态中的
isLoading设为true - 保留现有数据(避免加载过程中UI空白)
- 清空之前的错误信息(因为是新的请求流程)
示例代码:
fun ApiResponse<Day>.toDayState(currentState: DayState): DayState { return when (this) { is ApiResponse.Loading -> currentState.copy( isLoading = true, errorMessage = null ) // 你的Success处理逻辑 is ApiResponse.Success -> currentState.copy( isLoading = false, dayData = this.data, errorMessage = null ) is ApiResponse.Error -> { // 后续处理Error的逻辑 } } }
2. 处理Error状态
当接收到ApiResponse.Error时,需要传递错误信息并结束加载状态:
- 将
isLoading设为false - 提取错误信息(可以用默认提示兜底)
- 保留现有数据(避免加载失败后UI无内容)
示例代码:
fun ApiResponse<Day>.toDayState(currentState: DayState): DayState { return when (this) { // Loading和Success处理逻辑 is ApiResponse.Error -> currentState.copy( isLoading = false, errorMessage = this.message ?: "加载失败,请稍后重试" ) } }
在ViewModel中收集Flow时,结合viewModelScope处理状态更新:
viewModelScope.launch { supabaseRepository.getDayData() .map { it.toDayState(currentDayState.value) } .collect { newState -> currentDayState.value = newState } }
二、单次API调用:挂起函数还是Flow?
这个选择核心看业务需求和状态管理方式:
1. 优先用挂起函数的场景
如果是纯一次性请求(比如获取单条详情、提交表单、删除数据),且不需要持续监听数据变化,挂起函数更简洁:
- 代码逻辑直接,不需要处理Flow的收集和生命周期
- 用
try-catch就能直接处理异常,返回单一结果
示例:
// Repository层 suspend fun getDayData(): Day { return supabaseClient.from("days").select().single() } // ViewModel层 fun fetchDayData() { viewModelScope.launch { _currentDayState.value = _currentDayState.value.copy(isLoading = true) try { val data = repository.getDayData() _currentDayState.value = _currentDayState.value.copy( isLoading = false, dayData = data ) } catch (e: Exception) { _currentDayState.value = _currentDayState.value.copy( isLoading = false, errorMessage = e.message ?: "请求失败" ) } } }
2. 优先用Flow的场景
如果满足以下任一情况,Flow(尤其是StateFlow)更合适:
- 需要持续监听数据变化:比如Supabase的实时订阅,后端数据更新后会主动推送到客户端,必须用Flow接收
- ViewModel需要统一管理UI状态:把加载、成功、错误状态都包装到一个
StateFlow里,UI只需收集这一个流就能处理所有状态,避免分散管理 - 需要使用Flow操作符:比如对请求结果做转换、合并、防抖等操作,Flow的操作符生态更强大
总结
- 纯单次无更新的请求:用挂起函数+手动维护UI状态,代码更简单
- 需要实时更新或统一状态管理:用Flow(StateFlow)包装整个请求生命周期的状态
内容的提问来源于stack exchange,提问作者Joyce Opio
相关产品推荐
相关产品推荐

