Manoj Perumarath
Manoj Perumarath

Reputation: 10254

How to handle fragments sharing same viewmodel and livedata cause same action on both fragments?

I have a SignUpFragment in which Firebase is used for signing up and a livedata observer is there.

SignUpFragment

    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()
            }
        }
    })

When a user successfully sign up, I'm navigating him to the Login Screen, but in login screen there's also a livedata observer which uses the same variable.

LoginFragment

    // 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()
            }
        }
    })

Here you can see that the condition will be true for both cases and Login screen switches to HomeScreen.

How can I handle such a situation? Please note that I'm sharing viewmodel using

 private val viewModel: AuthViewModel by activityViewModels()

Also replaced this with viewLifecycleOwner but still no hope.

Upvotes: 1

Views: 157

Answers (1)

Parag Pawar
Parag Pawar

Reputation: 867

Okay, so continuing our discussion here, you're sharing ViewModel between fragments, so when you're observing the particular live data in the fragment, you're not reinitializing it instead you're using the same instance. So there can be 2 ways you can handle this. One: Stop sharing your ViewModel, or remove your observer as soon as you change the flag.

this is the 2nd way:

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)

You might have to define your mUserObserver first(outside the function).

Try this and let me know

Upvotes: 1

Related Questions