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

Android Kotlin:Github API重复加载失败,ResultViewModel.Loading始终为false

GitHub用户详情页无法重新加载,Loading状态始终为false的问题分析与修复

核心问题原因

1. getUser方法加载状态发送时机错误

在getUser的flow逻辑中,先执行了同步网络请求repository.getDetailUserFromGithub(username),之后才设置Loading(true)。这意味着网络请求完成后才通知UI“开始加载”,紧接着就会发送Success状态,Loading(true)会被快速覆盖。后续再次调用时,网络请求因缓存或速度快,这个过程更短,最终仅能捕捉到onCompletion发送的Loading(false)。

2. getFollowingUser存在递归调用错误

getFollowingUser方法的flow块中,错误调用了自身方法getFollowingUser(username),而非仓库层的repository.getFollowingUserFromGithub(username),导致无限递归,请求无法正常完成。

3. Activity中重复调用getUser

DetailUserActivity的onCreate里连续两次调用viewModel.getUser(username),既浪费资源,也可能导致请求结果被覆盖。

4. LiveData状态覆盖问题

Loading(true)被后续状态快速覆盖,再次进入页面时,LiveData可能保留之前的Loading(false)状态,新的加载状态无法正确触发UI更新。

修复方案

1. 修正getUser的加载状态时机

将Loading(true)移到onStart操作符中,确保请求开始前通知UI:

fun getUser(username: String) {
    viewModelScope.launch {
        flow {
            val response = repository.getDetailUserFromGithub(username)
            emit(response)
        }.onStart {
            resultDetailUser.value = ResultViewModel.Loading(true)
        }.onCompletion {
            resultDetailUser.value = ResultViewModel.Loading(false)
        }.catch {
            Log.e("Error ", it.message.toString())
            it.printStackTrace()
            resultDetailUser.value = ResultViewModel.Error(it)
        }.collect {
            resultDetailUser.value = ResultViewModel.Success(it)
        }
    }
}

2. 修复getFollowingUser的递归错误

改为调用仓库层方法:

fun getFollowingUser(username: String) {
    viewModelScope.launch {
        flow {
            val response = repository.getFollowingUserFromGithub(username)
            emit(response)
        }.onStart {
            resultFollowingUser.value = ResultViewModel.Loading(true)
        }.onCompletion {
            resultFollowingUser.value = ResultViewModel.Loading(false)
        }.catch {
            Log.e("Error ", it.message.toString())
            it.printStackTrace()
            resultFollowingUser.value = ResultViewModel.Error(it)
        }.collect {
            resultFollowingUser.value = ResultViewModel.Success(it)
        }
    }
}

3. 移除重复的getUser调用

删除DetailUserActivity中resultDetailUser.observe之后的viewModel.getUser(username),仅保留一次调用(放在observe注册完成后)。

4. 页面进入时强制刷新(可选)

在DetailUserActivity的onResume中调用viewModel.getUser(username),确保每次进入页面都触发数据刷新,此时UI会正确收到Loading(true)通知。

额外优化建议

  • 给ResultViewModel添加泛型参数,避免类型转换:
sealed class ResultViewModel<out T> {
    data class Success<out T>(val data: T) : ResultViewModel<T>()
    data class Error(val exception: Throwable) : ResultViewModel<Nothing>()
    data class Loading(val isLoading: Boolean) : ResultViewModel<Nothing>()
}
  • 仓库层网络请求使用suspend挂起函数,配合Retrofit Coroutine支持,确保异步执行。
  • 给LiveData添加distinctUntilChanged(),避免重复状态触发UI更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 15:48:10