how to initialise ViewModel in createFragment of FragmentStateAdapter?

360 Views Asked by At

I have a ExerciseDetailFragment that contains an ExerciseFragmentStatePagerAdapter to show a bunch of SupportUsFragmentCard. These cards can be swiped horizontally by the user.

enter image description here

In my ExerciseFragmentStatePagerAdapter I have the following code:

fun createFragment(position: Int): Fragment {
    val exercise = exercises[position]
    val card = SupportUsFragmentCard()
    card.setExercise(exercise) <---- this is my question/problem
    return card
}

As you can see the pager adapter just instantiates the SupportUsFragmentCard and for this the exercise needs to be passed along (the card displays some exercise information) via the setExercise.

The SupportUsFragmentCard looks like this:

open class SupportUsFragmentCard : RootFragment() {
    ...
    val viewModel: SupportUsViewModel by viewModels()
    ...

    fun setExercise(exercise: Exercise?) {
        viewModel.setExercise(exercise) <---- passes on the exercise to the viewModel
    }

It’s implementation passes along the exercise to the underlying viewModel. Which in its turn encapsulates this into a LiveData (on which the SupportUsFragmentPlain has observers but I omitted this code as its not the issue):

class SupportUsViewModel() : ViewModel() {

    //interface to the view
    fun getExercise(): LiveData<Exercise?> = exercise
    fun setExercise(execise: Exercise?) {
        exercise.value = execise. <--- updates the Livedata object
    }

    //underlying live data mutable values
    private val exercise = MutableLiveData<Exercise?>(null)
}

When this code is executed, it crashes with exception:

IllegalStateException: Can't access ViewModels from detached fragment

I think because the createFragment ends up updating the viewModel without actually already being on screen. I also feel that this way of working does not respect the MVVM architecture.

What is the correct way in this scenario, using MVVM and LiveData to initialise the SupportUsViewModel with an Exercise in the ExerciseFragmentStatePagerAdapter's createFragment function?

0

There are 0 best solutions below