登出时如何清除ViewModel?登出再登录后LiveData无法被观察
问题分析与解决方案
问题描述
用户登出后再次登录,RecentLinkFragment中的Observer无法观察MainViewModel的usersLiveData更新,但重启应用后恢复正常,怀疑与ViewModel作用域有关。
根本原因
- ViewModel初始化逻辑只执行一次:
MainViewModel的init块仅在ViewModel创建时运行一次。若用户登出后主页Fragment未被销毁(比如Activity保留在后台),再次登录时ViewModel不会重建,导致新用户的数据请求不会触发。 - Repository未重置旧数据:登出时未清空Repository中保存的旧用户数据,新登录后若未主动刷新,LiveData会持有旧值或无更新。
- 数据请求时机不匹配:登录成功后没有主动触发新用户的数据拉取,仅依赖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
相关产品推荐
相关产品推荐

