从第二个片段访问时 ViewModel 数据丢失状态

Cod*_*ody 2 android mvvm android-fragments android-livedata android-viewmodel

我用于保存用户登录数据的 ViewModel 遇到问题。

用户登录后,我使用片段 A 中的用户数据更新此 ViewModel,但是当我尝试访问片段 B 中的数据时,我刚刚设置的数据字段始终为空。

当片段 B 初始化时,userLiveData 字段最初不会被观察到,但是,当我user从片段 B 触发对对象的更改时,会在片段 B 中正确观察到更改。看来我的 ViewModel 中字段的先前值永远不会到达片段B,但是新的价值观可以。

为了进行完整性检查,我创建了一个简单的字符串变量(甚至不是 LiveData 对象),将其设置为片段 A 中的值,然后,在导航到片段 BI 后打印该值:它每次都未初始化。就好像我注入到片段 B 中的 ViewModel 与我注入到片段 A 中的 ViewModel 完全分开。

我缺少什么导致片段 B 中的 ViewModel 观察最初不使用user片段 A 中设置的最后一个已知值触发?

片段A

class FragmentA : Fragment() {
    private val viewModel: LoginViewModel by viewModel()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel.user.observe(this, {
            it?.let {
                //Called successfully every time
                navigateToFragmentB()
            }
        })
        
        val mockUserData = User()
        viewModel.loginSuccess(mockUserData)
    }
}

Run Code Online (Sandbox Code Playgroud)

片段B

class FragmentB : Fragment() {
    private val viewModel: LoginViewModel by viewModel()
    
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        ...
        
        viewModel.user.observe(viewLifecycleOwner, { user ->
            user?.let {
                binding.initialsBubble.text = user.getInitials()
            } ?: navigateAway()
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

视图模型

class LoginViewModel(
    private val loginRepo: LoginRepo
) : ViewModel() {
    private val _user = MutableLiveData<User?>()
    val user: LiveData<User?> = _user
    

    fun loginSuccess(result: AuthenticationResult) {
        val user = loginRepo.login(result)
        _user.postValue(user)
    }
}
Run Code Online (Sandbox Code Playgroud)

Mad*_*adi 6

您应该对这两个片段使用sharedViewModel 。

在两个片段中使用这些代码行

private val viewModel: LoginViewModel by activityViewModels()
Run Code Online (Sandbox Code Playgroud)

代替

private val viewModel: LoginViewModel by viewModel()
Run Code Online (Sandbox Code Playgroud)