Android技术疑问:在Repository层轮询API是否合理?
Repository定时轮询数据实现的问题与优化方案
你当前在Repository的初始化块中,通过GlobalScope.launch启动了一个无限协程,每隔5秒调用getData()接口获取数据,成功时更新本地data字段,并且会将这个Repository注入到所有需要的ViewModel中。对应的初始化代码如下:
init { GlobalScope.launch { while(true) { when (val response = getData()) { is ApiResponse.Success -> { response.data?.let { data = it } } else -> {} } delay(5000) } } }
现有实现存在的问题
GlobalScope的风险:GlobalScope属于全局协程作用域,它的生命周期不受Repository或ViewModel的约束。即便相关组件已经被销毁,这个轮询协程仍会持续运行,不仅会造成内存泄漏,还会在后台无谓消耗系统资源。- 错误处理缺失:代码仅处理了接口返回成功的情况,对请求失败、抛出异常等分支完全没有处理,既不利于排查问题,也无法给上层业务提供错误反馈。
- 数据更新无通知:如果
data是普通变量,ViewModel无法感知到它的变化,UI层也无法自动响应数据更新,达不到数据驱动UI的效果。
优化建议
替换全局协程作用域
为Repository创建专属的CoroutineScope,让协程生命周期与Repository绑定。在Repository被销毁时,调用scope.cancel()终止所有协程。示例:class YourRepository(private val externalScope: CoroutineScope) { private val scope = externalScope + CoroutineName("RepositoryPolling") // ... 其他代码 fun cleanUp() { scope.cancel() } }完善错误处理逻辑
在分支中添加日志记录或异常处理,方便问题排查:when (val response = getData()) { is ApiResponse.Success -> { response.data?.let { _data.value = it } } is ApiResponse.Error -> { Log.e("YourRepository", "数据请求失败: ${response.errorMessage}") } is ApiResponse.Exception -> { Log.e("YourRepository", "数据请求抛出异常", response.exception) } }使用可观察数据容器
将data替换为MutableStateFlow(或LiveData),让ViewModel可以监听数据变化:private val _data = MutableStateFlow<YourDataType?>(null) val data: StateFlow<YourDataType?> = _data // 对外暴露只读流 init { scope.launch { while(isActive) { // 用isActive判断协程是否存活,避免不必要的循环 val response = getData() when (response) { is ApiResponse.Success -> response.data?.let { _data.value = it } is ApiResponse.Error -> Log.e("YourRepository", "请求失败: ${response.errorMessage}") is ApiResponse.Exception -> Log.e("YourRepository", "请求异常", response.exception) } delay(5000) } } }添加协程存活判断
在循环中通过isActive判断协程是否还处于活跃状态,避免协程被取消后仍执行无效逻辑。
内容的提问来源于stack exchange,提问作者Hasan Syed
相关产品推荐
相关产品推荐

