A ViewModel holds UI-related data and survives configuration changes (like screen rotation) that would otherwise destroy and recreate an Activity/Fragment, losing in-memory state.
class CounterViewModel : ViewModel() {
private val _count = MutableLiveData(0)
val count: LiveData<Int> = _count // exposed as read-only
fun increment() {
_count.value = (_count.value ?: 0) + 1
}
}
class CounterFragment : Fragment() {
private val viewModel: CounterViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.count.observe(viewLifecycleOwner) { newCount ->
binding.countText.text = newCount.toString()
}
binding.incrementButton.setOnClickListener { viewModel.increment() }
}
}
Exposing a private MutableLiveData alongside a public read-only LiveData is a deliberate pattern: the Fragment can observe changes but cannot directly mutate the ViewModel’s state, keeping state changes centralized in one place.
viewLifecycleOwner (not this) matters here — observing with the Fragment’s own lifecycle can cause the observer to fire on a destroyed view.
- Image
- SKU
- Rating
- Price
- Stock
- Availability
- Add to cart
- Description
- Content
- Weight
- Dimensions
- Additional information