【问题标题】:How to handle fragments sharing same viewmodel and livedata cause same action on both fragments?如何处理共享相同视图模型和实时数据的片段导致两个片段上的相同操作?
【发布时间】:2020-05-04 06:40:50
【问题描述】:

我有一个 SignUpFragment,其中 Firebase 用于注册,并且有一个 livedata 观察者。

注册片段

    viewModel.userMediatorLiveData.observe(this, Observer {
        Timber.i("Screen", this.javaClass.simpleName)
        if (it.status != null && it.message != null) {
            btn_sign_up.showSnack(it.message)
            if (it.status) {
                PreferenceHelper.userPassword = tie_password.getTrimmedText()
                returnToLoginScreen()
            }
        }
    })

当用户成功注册后,我会将他导航到登录屏幕,但在登录屏幕中还有一个使用相同变量的 livedata 观察者。

登录片段

    // this observer is used also for listening to Firebase Login
    viewModel.userMediatorLiveData.observe(this, Observer {
        Timber.i("Screen", this.javaClass.simpleName)
        if (it.status != null && it.message != null) {
            btn_login.showSnack(it.message)
            if (it.status) {
                PreferenceHelper.userPassword = tie_password.getTrimmedText()
                context?.startActivity(HomeActivity::class.java)
                requireActivity().finish()
            }
        }
    })

在这里您可以看到两种情况的条件都为真,登录屏幕切换到 HomeScreen。

我该如何处理这种情况? 请注意,我正在使用

共享视图模型
 private val viewModel: AuthViewModel by activityViewModels()

还将this 替换为viewLifecycleOwner,但仍然没有希望。

【问题讨论】:

  • 所以基本上你想在片段之间共享你的 ViewModel 和它的内容,对吧?
  • 你也可以展示你是如何在片段中初始化你的视图模型的吗?
  • @ParagPawar 不,我有一个通用的 livedata 变量来处理登录和注册的结果,当注册完成时,我正在导航到登录屏幕,但登录中的 livedata 观察者也是如此,因为注册是真的。
  • 好吧,如果我理解正确,您希望用户在完成注册后登录,但它会直接进入主屏幕,因为您正在观察相同的 MediatorLiveData,对吧?
  • @ParagPawar 你明白了!

标签: android fragment viewmodel android-livedata


【解决方案1】:

好的,继续我们的讨论,您在片段之间共享 ViewModel,因此当您观察片段中的特定实时数据时,您并没有重新初始化它,而是使用相同的实例。所以有两种方法可以处理这个问题。一:停止共享您的 ViewModel,或在更改标志后立即删除您的观察者。

这是第二种方式:

val mUserData = viewModel.userMediatorLiveData

val mUserObserver = Observer {
    Timber.i("Screen", this.javaClass.simpleName)
    if (it.status != null && it.message != null) {
        btn_login.showSnack(it.message)
        if (it.status) {
            PreferenceHelper.userPassword = tie_password.getTrimmedText()
            context?.startActivity(HomeActivity::class.java)
            requireActivity().finish()
            //notice this
            mUserData.removeObserver(mUserObserver)
        }
    }
}

mUserData.observe(viewLifecycleOwner, mUserObserver)

您可能必须先定义您的 mUserObserver(在函数之外)。

试试这个,让我知道

【讨论】:

  • 我认为这不适用于您的情况,因为 firebase 将始终告诉您用户已登录,直到您明确注销该用户。您能否也分享您的firebase代码,以便我对其有清晰的了解
  • 当我调用这个观察者时,它具有旧值,在注册屏幕中设置为 true
  • 是的,因为它从 firebase 获取数据,而 firebase 总是会返回登录状态,请在 ViewModel 中发布与代码相关的 userMediatorLiveData 实现。
猜你喜欢
  • 2017-09-12
  • 2020-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多