I have a ExerciseDetailFragment
that contains an ExerciseFragmentStatePagerAdapter
to show a bunch of SupportUsFragmentCard
. These cards can be swiped horizontally by the user.
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?