如何在Retrofit中重新发起请求实现下拉刷新获取更新数据?
实现下拉刷新重新获取API数据
核心思路
下拉刷新是用户主动触发的重新请求,不需要依赖OkHttp拦截器(拦截器多用于自动重试失败请求,比如网络波动时)。只需在ViewModel中暴露刷新方法,配合Compose的SwipeRefresh组件即可实现。
步骤1:修改ViewModel,添加刷新方法
把原本私有数据获取方法包装成可外部调用的刷新函数,确保重新请求时能正确更新状态:
@HiltViewModel class MatchesViewModel @Inject constructor( private val matchRepository: MatchRepository ): ViewModel() { val response: MutableState<ApiState> = mutableStateOf(ApiState.Empty) init { getAllMatches() } // 暴露给外部调用的刷新方法 fun refreshMatches() = viewModelScope.launch { getAllMatches() } private fun getAllMatches() = viewModelScope.launch { matchRepository.getAllMatches() .onStart { response.value = ApiState.Loading } .catch { response.value = ApiState.Failure(it) } .collect { response.value = ApiState.Success(it) } } }
步骤2:在Compose中添加下拉刷新组件
使用Jetpack Compose自带的SwipeRefresh包裹页面内容,关联刷新状态并触发刷新:
@Composable fun MainScreen(viewModel: MatchesViewModel = hiltViewModel()){ // 根据当前状态判断是否处于刷新中 val isRefreshing = viewModel.response.value is ApiState.Loading SwipeRefresh( state = rememberSwipeRefreshState(isRefreshing = isRefreshing), onRefresh = { viewModel.refreshMatches() } // 下拉时触发刷新 ) { when (val result = viewModel.response.value){ is ApiState.Success -> { HomeScreen(matches = result.data.data) } is ApiState.Loading -> { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { CircularProgressIndicator() } } is ApiState.Empty -> { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text(text = "暂无数据") } } is ApiState.Failure -> { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text(text = "加载失败:${result.exception.message ?: "未知错误"}") } } } } }
补充说明
SwipeRefresh会自动处理下拉时的刷新指示器,无需额外编写动画逻辑。- 若需要实现自动重试失败请求(比如网络差时自动重试),才需要用到OkHttp拦截器,可通过OkHttp的
RetryInterceptor配置重试次数、重试条件(如HTTP 5xx错误)。
内容的提问来源于stack exchange,提问作者jaskaran singh
相关产品推荐
相关产品推荐

