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

登出时如何清除ViewModel?登出再登录后LiveData无法被观察

问题分析与解决方案

问题描述

用户登出后再次登录,RecentLinkFragment中的Observer无法观察MainViewModel的usersLiveData更新,但重启应用后恢复正常,怀疑与ViewModel作用域有关。

根本原因

  1. ViewModel初始化逻辑只执行一次:MainViewModel的init块仅在ViewModel创建时运行一次。若用户登出后主页Fragment未被销毁(比如Activity保留在后台),再次登录时ViewModel不会重建,导致新用户的数据请求不会触发。
  2. Repository未重置旧数据:登出时未清空Repository中保存的旧用户数据,新登录后若未主动刷新,LiveData会持有旧值或无更新。
  3. 数据请求时机不匹配:登录成功后没有主动触发新用户的数据拉取,仅依赖ViewModel初始化时的请求,导致Fragment Observer收不到新数据。

解决方案

1. 给ViewModel添加主动刷新方法

在MainViewModel中新增刷新数据的方法,用于登录成功后主动触发新用户的数据请求:

@HiltViewModel
class MainViewModel @Inject constructor(
    private val repository: UserRepository,
    private val firebaseAuth: FirebaseAuth
) : ViewModel() {
    // ... 原有代码 ...

    // 新增:主动刷新用户数据
    fun refreshUserData() {
        viewModelScope.launch {
            repository.getUsersData()
        }
    }
}

2. 完善Repository的清空逻辑

给UserRepository添加清除LiveData的方法,确保登出时旧数据被重置:

class UserRepository @Inject constructor(
    private val linkProApi: LinkProApi,
    private val firebaseAuth: FirebaseAuth
) {
    // ... 原有代码 ...

    // 新增:清空LiveData中的旧数据
    fun clearLiveData() {
        _data.postValue(null)
    }
}

3. 登录成功后触发数据刷新

在登录流程完成(比如Google登录成功、Firebase认证完成)后,调用ViewModel的刷新方法拉取新用户数据:

fun firebaseAuthWithGoogle(account: GoogleSignInAccount) {
    // ... 原有Firebase认证逻辑 ...
    // 登录成功后,触发数据刷新
    viewModelScope.launch {
        val mainViewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java)
        mainViewModel.refreshUserData()
    }
}

4. 优化Fragment的可见性触发刷新(可选)

在RecentLinkFragment的onResume方法中调用刷新,确保每次Fragment可见时都能获取最新数据:

@AndroidEntryPoint
class RecentLinkFragment : Fragment() {
    // ... 原有代码 ...

    override fun onResume() {
        super.onResume()
        mainViewMdoel.refreshUserData()
    }
}

5. 修复Repository中数据解析的潜在问题

原代码中result.body()!!.string()只能调用一次(ResponseBody流会被消耗),修改为先保存字符串再解析:

suspend fun getUsersData() {
    try {
        val result = linkProApi.getLinkData(Id(firebaseAuth.currentUser!!.uid.toString()))
        if (result.isSuccessful && result.body() != null) {
            val bodyContent = result.body()!!.string()
            val userData: Data = Gson().fromJson(bodyContent, Data::class.java)
            _data.postValue(userData)
        } else {
            _data.postValue(null) // 请求失败时更新LiveData,避免Observer一直等待
        }
    } catch (e: Exception) {
        Log.d("data", e.toString())
        _data.postValue(null) // 异常时也更新LiveData
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 06:04:51