Android LiveData 在导航返回后观察到陈旧数据

标签 android android-architecture-components android-livedata android-mvvm android-architecture-navigation

问题:

如何防止我的实时数据在向后导航时立即接收到陈旧数据?我正在使用概述的 Eventhere我认为这会阻止这种情况。

问题:

我使用登录 fragment 打开应用程序,并在设置实时数据电子邮件/密码时导航到注册 fragment (后端调用说“这是一个新帐户去注册”)。如果用户在注册过程中点击后退按钮,Android 会弹回登录。 当按回键后登录 fragment 被重新创建时,它会立即使用陈旧的后端响应再次触发实时数据,我想防止这种情况发生。

登录 fragment .kt

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    subscribeToLoginEvent()
}

private fun subscribeToLoginEvent() {
    //When a back press occurs, we subscribe again and this instantly 
    //fires with the same data it used to leave the screen 
    //(a Resource<User> with status=SUCCESS, data = null)

    viewModel.user.observe(viewLifecycleOwner, Observer { response ->
        Timber.i("login event observed....status:" + response?.status + ", data: " + response?.data)
        binding.userResource = response

        response?.let {
            val status = it.status
            val message = it.message

            if (status == Status.SUCCESS && it.data == null) {
                //This is a brand new user so we need to register now 
                navController()
                .navigate(LoginFragmentDirections.showUserRegistration()))
            }
            else if(status == Status.SUCCESS && it.data != null){
                goHome()
            }
        }
    })
}

登录 View 模型.kt

private val _loginCredentials: MutableLiveData<Event<Pair<String, String>>> = MutableLiveData()

val user: LiveData<Resource<User>> = Transformations.switchMap(_loginCredentials) {
    val data = it.getContentIfNotHandled()
    if(data != null && data.first.isNotBlank() && data.second.isNotBlank())
        interactor.callUserLoginRepo(data.first, data.second)
    else
        AbsentLiveData.create()
}

最佳答案

好的,这里有两个问题,希望对其他人有所帮助。

  • 首先是 Event 类似乎无法处理转换。我认为这是因为事件实际上指向了错误的实时数据(_login_credentials vs user)
  • 第二个问题有点更根本,但现在也很明显。我们到处都被告知,实时数据观察会在订阅时发出最新数据,以确保您获得最新数据。这意味着我在这里使用实时数据的方式完全不正确,我无法订阅登录事件、导航到某个地方、导航回来并重新订阅,因为 ViewModel 正确地给我它拥有的最新数据(因为登录 fragment 只是分离,从未被摧毁)。

解决方案

解决方案是将执行获取一个 fragment 的逻辑简单地移动到更深的位置。因此,我不需要监听用户凭据 + 登录单击 -> 获取用户 -> 然后导航到某处,而是需要监听用户凭据 + 登录单击 -> 导航某处 -> 然后然后开始订阅我的用户实时数据。这样我就可以随心所欲地返回登录屏幕,而不是订阅一些从未被破坏的陈旧实时数据。如果我返回登录然后转发订阅和 fragment 被销毁,那么在这种情况下我将适本地获取新数据。

关于Android LiveData 在导航返回后观察到陈旧数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53031767/

相关文章:

android - 数据更改时不会调用 LiveData onChanged

android - 在 DAO 查询方法中将 POJO 作为参数传递以更新列的子集?

android - 如何为底部导航制作导航图?有没有办法修改返回堆栈的行为?

android - 缓存在 Android Paging 3 中不起作用

android - ViewModel 在导航导航中没有被清除,并且 viewmodel 中的实时数据保持 Activity 状态

flutter - Flutter 中的 Android LiveData 相当于什么?

android - 有什么方法可以同步我的 avd 的时钟

Android - 每天凌晨 4 点运行服务

java - JSoup - 提取 div 的内容时出错

java - Android 实时数据 : Transformation switchMap: Apply filter on the original list and show the filtered data