6

I'm using a shared ViewModel in Navigation component rather than creating a ViewModel for every fragment (mostly because it's easier) but now I have a problem when I re-enter a fragment and subscribe to the ViewModel live data of that fragment, I get the last state also too.

here is the ViewModel Code:

  val apiLessonData: MutableLiveData<String>> = MutableLiveData()
  fun getLessonsUserCreated() =
        apiCall(MyMaybeObserver(apiLessonData))

in MyMaybeObserver, I have somthing like this:

override fun onSuccess(t: T) {
    apiDataObserver.postValue(t)
}

and this is how I observe it in my fragment:

private val apiAddGoalData = Observer<String> { response ->
    showSnack(response)
}

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        .
        .
        viewModel.apiAddGoalData.observe(viewLifecycleOwner, apiAddGoalData)
        .
        .
    }

now when I enter the first time it works fine but I open it the second time, it shows the snack from the previous time, how to stop this without creating new ViewModel?

Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38

2 Answers2

3

In the simple way You could set null for your MutableLiveData after getting data in onchange method of the observer. For more information you can read this article:livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case . also you can see this question maybe help you: How to clear LiveData stored value?

maryam
  • 1,437
  • 2
  • 18
  • 40
  • I agree it is the simplest way, I can even call this viewModel.livedata= MutableLiveData() everytime fragment opens, but I thought there might be a better way so ill read through your links. and how cool is that, that you are from isfahan too :)) – Amin Keshavarzian Oct 20 '19 at 09:12
  • If you get your correct answer, Please select my answer as the best. – maryam Oct 20 '19 at 16:33
1

I don't think your problem is with the LiveData since you are wisely using the viewLifecycleOwner, problem is with the state of the view and lifeCycle of the fragment. With navigation component of jetpack, fragments get replaced in the container. Think of this scenario: You open fragment A then you navigate to frament B and press back button to return to fragment A. onCreateView and onViewCreated methods of the fragment A gets called again. Since the onDestroy of fragment A haven't been called when you opened fragment B some of the view states will be restored while returning to A. This is as you might know the same reason we use viewLifecycleOwner. So Nullify or clear the state of the views in the onDestroyView of the fragment A:

recyclerView.setAdapter(null)
checkBox.setChecked(false)
Sina
  • 2,683
  • 1
  • 13
  • 25
  • Hi, thanks for long description, but my problem is the other way around, I go from fragment A to B and load some data in B, and then navigateUp to fragment A and then when re-enter fragment B I get the latest state which forces my view to update it with previuos data which is not valid anymore ... however, +1 for you time :) – Amin Keshavarzian Oct 20 '19 at 08:41
  • No problem at all. What you described is similar to what I said. Your problem is just with the second fragment. It has nothing to do with LiveData and single Viewmodel design. We had this problem with one Viewmodel for each fragment design too. You can nullify your livedata, but, the view which supposed to take state from livedata, at least shows the previous state for a second. For example the check a checkbox and don't save it to the database, on return to the fragment, checkbox is checked at first no matter what is the value for it in the database. – Sina Oct 21 '19 at 04:19