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

Jetpack Compose登录后userState始终处于Loading状态问题求助

登录状态无法从Loading切换到Success的排查与修复

核心问题梳理

登录完成后userState始终停留在Loading状态,未切换至Success,需从副作用处理、异常捕获、状态分支覆盖三个方向排查。


1. Composable中非法的副作用操作

问题代码

在DashboardScreen的Loading分支中直接修改ViewModel的isLoggedIn状态:

AuthenticatedUserState.Loading -> {
    CircularProgressIndicator()
    viewModel.isLoggedIn = true // 非法副作用操作
}

原因

Composable是纯UI描述函数,不应包含状态修改这类副作用。每次userState触发重组时,都会执行该赋值,可能导致逻辑混乱,甚至干扰状态更新流程。且isLoggedIn的赋值逻辑已在handleAuthResult的Authorized分支中实现,此处属于重复且错误的操作。

修复

删除Composable中的状态赋值,仅保留UI渲染:

AuthenticatedUserState.Loading -> {
    CircularProgressIndicator()
}

2. 异常捕获不完整,导致状态无更新

问题点1:authenticatedUser仅捕获HttpException,未覆盖所有异常

原代码仅在响应成功判断后捕获异常,且只处理HttpException:

private suspend fun authenticatedUser(token: String) {
    val authenticatedUserResponse = sessionRepository.getUserFirstName(token)
    val authenticatedUserDetails = authenticatedUserResponse.body()
    try {
        if (authenticatedUserResponse.isSuccessful) {
            _userState.value = AuthenticatedUserState.Success(authenticatedUserDetails)
            println("user state: ${userState.value}")
        }
    } catch (error: HttpException) {
        _userState.value = AuthenticatedUserState.Error
    }
}

原因

  • 网络超时、无网络等场景会抛出IOException,未被捕获
  • 响应非成功状态(如401、500)时,未设置Error状态,导致userState一直停留在Loading

修复

将整个请求逻辑包裹在try-catch中,捕获所有异常,并处理非成功响应:

private suspend fun authenticatedUser(token: String) {
    try {
        val authenticatedUserResponse = sessionRepository.getUserFirstName(token)
        val authenticatedUserDetails = authenticatedUserResponse.body()
        if (authenticatedUserResponse.isSuccessful) {
            _userState.value = AuthenticatedUserState.Success(authenticatedUserDetails)
            println("user state: ${userState.value}")
        } else {
            // 处理4xx/5xx等非成功响应
            _userState.value = AuthenticatedUserState.Error
        }
    } catch (error: Exception) {
        Log.d("Error", error.message ?: "Unknown error")
        _userState.value = AuthenticatedUserState.Error
    }
}

问题点2:userIsLoggedIn仅捕获HttpException

原代码仅捕获HttpException,未处理其他网络异常:

catch (error: HttpException) {
    _userState.value = AuthenticatedUserState.Error
}

修复

改为捕获Exception,覆盖所有可能的异常场景:

catch (error: Exception) {
    Log.d("Error", error.message ?: "Unknown error")
    _userState.value = AuthenticatedUserState.Error
}

3. Token解析失败/为空时,未更新状态

问题代码

fetchAuthenticatedUser中仅当token不为null时才执行后续逻辑,为空时无任何状态更新:

private fun fetchAuthenticatedUser(token: String?) {
    viewModelScope.launch {
        try {
            if (token != null) {
                authenticatedUser(token)
            }
            // token为空时无状态更新
        } catch (error: Exception) {
            Log.d("Error", error.message ?: "Unknown error")
            _userState.value = AuthenticatedUserState.Error
        }
    }
}

原因

如果fetchSessionIdToken解析token失败返回null,后续不会触发任何状态更新,userState将一直停留在Loading。

修复

添加token为空的分支,设置Error状态:

private fun fetchAuthenticatedUser(token: String?) {
    viewModelScope.launch {
        try {
            if (token != null) {
                authenticatedUser(token)
            } else {
                // Token解析失败,更新为Error状态
                _userState.value = AuthenticatedUserState.Error
            }
        } catch (error: Exception) {
            Log.d("Error", error.message ?: "Unknown error")
            _userState.value = AuthenticatedUserState.Error
        }
    }
}

4. 额外验证点

  • 打印sessionRepository.loggedIn和getUserFirstName的响应状态码、内容,确认网络请求是否正常
  • 检查saveAuthToken是否正确保存token,避免后续请求因token无效失败
  • 验证AuthenticatedUserState.Success是否正确传递了非null的AuthenticationMessage(若UI依赖该数据)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 04:20:19