Reputation: 10887
I have a Fragment
that contains several CheckBox
es:
class TestFragment : Fragment() {
private lateinit var checkBox2er: CheckBox
private lateinit var checkBox3er: CheckBox
// ...
private lateinit var checkBox10er: CheckBox
private val activityViewModel: MainViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val rootView = inflater.inflate(R.layout.fragment_test, container, false)
checkBox2er = rootView.findViewById(R.id.checkbox2TT)
checkBox3er = rootView.findViewById(R.id.checkbox3TT)
// ...
checkBox10er = rootView.findViewById(R.id.checkbox10TT)
val checkBoxes = listOf(
checkBox2er, checkBox3er, checkBox4er, checkBox5er,
checkBox6er, checkBox7er, checkBox8er, checkBox9er, checkBox10er
)
// update CheckBox from ViewModel
// IS THIS ACTUALLY NEEDED?
lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
activityViewModel.testFactors.collect { updatedFactors: Set<Int> ->
Log.d(javaClass.simpleName, "testFactors was updated")
checkBoxes.forEach { checkBox ->
checkBox.tagNumber?.let { rowId -> checkBox.isChecked = updatedFactors.contains(rowId) }
}
}
}
}
// update ViewModel Set when a CheckBox is clicked
checkBoxes.forEach { checkBox ->
checkBox.setOnCheckedChangeListener { clickedCheckBox, isChecked ->
clickedCheckBox.tagNumber?.let { rowId ->
Log.d(javaClass.simpleName, "clicked CheckBox $rowId")
activityViewModel.toggleCheckbox(rowId, isChecked)
}
}
}
return rootView
}
}
val View.tagNumber: Int?
get() {
val stringTag = this.tag as? String
return stringTag?.toIntOrNull()
}
The layout of a CheckBox
looks like this:
<CheckBox
android:id="@+id/checkbox2TT"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:checked="true"
android:text="@string/TT2"
android:tag="2" />
I manage a Set
of all currently selected CheckBox
es in my ViewModel
:
class MainViewModel(application: Application) : AndroidViewModel(application) {
private val writableTestFactors: MutableStateFlow<Set<Int>> = MutableStateFlow(sortedSetOf(2,3,4,5,6,7,8,9,10))
val testFactors: StateFlow<Set<Int>> = writableTestFactors
fun toggleCheckbox(toggleRow: Int, isChecked: Boolean) {
val newSortedSet = TreeSet(testFactors.value)
if (isChecked) {
newSortedSet.add(toggleRow)
} else {
newSortedSet.remove(toggleRow)
}
writableTestFactors.value = newSortedSet
}
}
I am now confused whether the lifecycleScope.launch {}
is actually needed. The ViewModel should be the single source of truth in MVVM according to my understanding, but it seems like the Fragment
stores and restores the checked state of the CheckBox
es itself when the application process gets killed.
What should be the single source of truth here, and how would I properly implement a MVVM approach?
Upvotes: 0
Views: 30