2

I'm in trouble :D I starting to use mvvm and LiveData, and I want to do it in better way. I will try to explain you my doubt with a simple example :

I have a container fragment "Exams" containing a ViewPager2 that contain some fragments "Question".There are also ExamsViewModel and QuestionViewModel.There isn't db and my only data source is MyExamDataSource, something like this:

class MyExamDataSource {
    val questions:ArrayList<Question> = ArrayList()

    fun saveQuestionResult(){
      ...
    }

    fun getQuestion():Question{
      ...
    }

    ...
    ...
}

data class Question(val correct:Boolean, val selectedAnswers:ArrayList<Int>)

class ExamViewModel(myExamsDataSource: MyExamsDataSource): ViewModel() {

    val correctAnswer:LiveData<Int> = MutableLiveData<Int>(0)
    ...
    ...   
}

Every QuestionViewModel validate his own question, but in the sametime the correctAnswer LiveData should be incremented every time there are a new correct answer. MyExamData source is passed through the modelfactory to ExamsViewModel and QuestionViewModel.

But now I have some doubt:

  1. How can I update the correctAnswer LiveData ?
  2. If I trasform the questions field in a LiveData>, and the ExamsModelView observe it, the onChanged method is not called if I only edit an element of the list or I'm wrong ?
  3. Is better to make a directly comunication between modelview ?
aeroxr1
  • 841
  • 10
  • 27

1 Answers1

1

How can I update the correctAnswer LiveData ?

Using callbacks to the Exams fragment. Exam fragment will then update the correctAnswer in ViewModel

If I trasform the questions field in a LiveData>, and the ExamsModelView observe it, the onChanged method is not called if I only edit an element of the list or I'm wrong ?

If you add element to the list, it will not call the observers. There are workarounds to it. See Notify Observer when item is added to List of LiveData

Is better to make a directly comunication between modelview ?

ModelViews hold data for one or multiple views. Therefore, they should not communicate with each other. It goes against the MVVM architecture. If you are at such a position, considering using one ModelView for multiple views. This is often practiced by creating one ModelView with the activity which holds data for all the fragments in that activity too.

  • Hi :) Thanks ;) The calback in Exams fragment it seems not clean, right ? Maybe the better solution for my case is one model for all the views ? What do you think about two model and shared data source ? "If you add element to the list, it will not call the observers. There are workarounds to it. See Notify Observer when item is added to List of LiveData" In my case I would update only a field inside an object already present in the list o.O – aeroxr1 Jun 20 '20 at 21:55
  • Yes. I agree. Callbacks solution is not clean. Having one view model for multiple views is a better approach here. – Ahtsham Abbasi Jun 22 '20 at 04:08
  • 1
    For your live data list, if you have a single view model, you can create a function to update the data in the live data list and then simply force refresh it in the last line of that function. To make force refreshing reusable, you can also create an extension function on LiveData class called force refresh which just does "this.value = this.value" – Ahtsham Abbasi Jun 22 '20 at 04:13
  • Thanks :) I'm wondering if is better to use a view instead a fragment in the viewPager. – aeroxr1 Jun 22 '20 at 06:33
  • 1
    what is your use case? if your view doesn't need to be aware of lifecycle events then fragments might be an overkill. – Ahtsham Abbasi Jun 22 '20 at 17:17
  • every page should show a list with an header, every item of list has a checkbox and out of viewPager2 I have to know which elements was selected. Thanks to your help :) – aeroxr1 Jun 22 '20 at 20:23
  • yes this can be easily achieved with views as well. You are welcome. – Ahtsham Abbasi Jun 24 '20 at 04:04
  • I have used the solution with one model for each fragment. Now I have one little problem, the Transformations continue to observe the dataSource liveData because when I swipe from a page to an other the onCleared method is not called :/ – aeroxr1 Jul 01 '20 at 09:26