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

首次点击触发API未等待响应,导致UserAuth数据未更新的问题解决

问题描述

点击事件调用checkUserforEmnail函数时,首次点击打印的userData为null,再次点击才能正常获取到数据。原因是API响应需要时间,代码未等待响应返回就直接使用了默认的null值;第二次点击时能获取到已更新的userData。

相关代码

UI层代码

var authViewModel: UserAuthViewModel = hiltViewModel()
val userData by authViewModel.authUserData.collectAsState()

fun checkUserforEmnail(
    sharedViewModel: SharedViewModel,
    userData: AuthResponseModel?,
    authViewModel : UserAuthViewModel,
    navController: NavController,
    textUser: String
) {
    Log.d("TAG", "checkUserforEmnail: ${userData}")
    if (userData == null){
        authViewModel.getAuthUserDataEmail(textUser = textUser)
        Log.d("TAG", "checkUserforEmnail: ${userData}")
    }
    if(userData?.result?.user_exist == "USER_NOT_EXISTS"){
        navController.navigate(NavScreens.REGISTRATION.route)
    }
    else if(userData?.result?.user_exist == "ACCOUNT_EXISTS") {
        sharedViewModel.addUsername(userName = textUser)
        navController.navigate(NavScreens.LOGIN.route)
    }
    else if(userData?.result?.user_exist == "ACCOUNT_NOT_VERIFIED"){

    }
}

ViewModel代码

@HiltViewModel
class UserAuthViewModel @Inject constructor(private val repository: Repository) : ViewModel()  {

    val authUserData: StateFlow<AuthResponseModel?> get() = repository.authUserData

    fun getAuthUserData(textUser: String, countryCode:String){
        viewModelScope.launch {
            val result = repository.getAuthUserData(AuthUser(username = textUser, country_dial_code = countryCode))
        }
    }

    fun getAuthUserDataEmail(textUser: String) {
        viewModelScope.launch {
            val result = repository.getAuthUserData(AuthUser(username = textUser))
        }
    }
}
解决方案

核心思路是不要在点击事件中同步判断异步返回的userData,而是通过观察StateFlow的状态变化来处理后续导航逻辑,同时添加加载状态避免重复请求:

1. 改造ViewModel,添加加载状态与状态更新逻辑

@HiltViewModel
class UserAuthViewModel @Inject constructor(private val repository: Repository) : ViewModel()  {

    // 自行维护MutableStateFlow,确保能主动更新状态
    private val _authUserData = MutableStateFlow<AuthResponseModel?>(null)
    val authUserData: StateFlow<AuthResponseModel?> = _authUserData

    private val _isLoading = MutableStateFlow(false)
    val isLoading: StateFlow<Boolean> = _isLoading

    fun getAuthUserData(textUser: String, countryCode:String){
        viewModelScope.launch {
            _isLoading.value = true
            try {
                val response = repository.getAuthUserData(AuthUser(username = textUser, country_dial_code = countryCode))
                _authUserData.value = response // 请求成功后更新状态
            } finally {
                _isLoading.value = false
            }
        }
    }

    fun getAuthUserDataEmail(textUser: String) {
        viewModelScope.launch {
            _isLoading.value = true
            try {
                val response = repository.getAuthUserData(AuthUser(username = textUser))
                _authUserData.value = response // 请求成功后更新状态
            } finally {
                _isLoading.value = false
            }
        }
    }

    // 处理完导航后重置状态,避免重复触发逻辑
    fun resetAuthUserData() {
        _authUserData.value = null
    }
}

2. 调整UI层逻辑,分离请求触发与状态处理

var authViewModel: UserAuthViewModel = hiltViewModel()
val userData by authViewModel.authUserData.collectAsState()
val isLoading by authViewModel.isLoading.collectAsState()
val textUser = remember { mutableStateOf("") } // 绑定输入框的文本状态

// 点击事件仅负责触发API请求,不处理后续导航
fun onCheckEmailClick(sharedViewModel: SharedViewModel, navController: NavController) {
    if (isLoading || textUser.value.isBlank()) return // 防止重复点击或空输入
    authViewModel.getAuthUserDataEmail(textUser.value)
}

// 用LaunchedEffect监听userData变化,自动处理导航
LaunchedEffect(userData) {
    userData?.let { data ->
        when(data.result?.user_exist) {
            "USER_NOT_EXISTS" -> navController.navigate(NavScreens.REGISTRATION.route)
            "ACCOUNT_EXISTS" -> {
                sharedViewModel.addUsername(textUser.value)
                navController.navigate(NavScreens.LOGIN.route)
            }
            "ACCOUNT_NOT_VERIFIED" -> {
                // 这里添加账号未验证的处理逻辑,比如弹窗提示用户验证
            }
        }
        // 处理完成后重置状态,避免页面重组时重复触发导航
        authViewModel.resetAuthUserData()
    }
}

3. 关键说明

  • 异步请求的结果通过StateFlow通知UI,UI在状态更新时自动重组,此时处理导航逻辑就能拿到最新的userData
  • 加载状态isLoading可以避免用户重复点击发起多次无效API请求
  • 处理完导航后重置authUserData,防止页面因其他原因重组时再次触发相同的导航逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:15:22