ViewModel
Objective
- The starter app doesn’t save and restore the app state during configuration changes, such as when the device orientation changes, or when the app shuts down and restarts.
onSaveInstanceState()requires us to add extra codes to save and retrieve the state from a bundle- We should keep the size of data in a bundle as minimal as possible. (Limitation on the size of a bundle, 500KB to 1MB)
- The game screen does not navigate to the score screen when the user taps the End Game button.
How to solve?
-
We can make it by using the recommended App architecture. This diagram shows how all the modules should interact with one another after designing the app.

-
This codelab follows the separation of concern design principle, dividing classes into sections addressing distinctive concerns.
- UI with Activity / Fragment
- ViewModel and Repository <- current scope
- Model and Data sources
Overview of ViewModel, ViewModelProvider, and ViewModelFactory
-
Definition of ViewModel
The
ViewModelclass is designed to store and manage UI-related data in a lifecycle conscious way. TheViewModelclass allows data to survive configuration changes such as screen rotations.A
ViewModelcan do simple calculations and transformations on data to prepare the data to be displayed by the UI controller. In this architecture, theViewModelperforms the decision-making, and UI component works according to the data transformed in the ViewModel.

implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'class GameViewModel : ViewModel() { init { Log.i("GameViewModel", "GameViewModel created!") } override fun onCleared() { super.onCleared() Log.i("GameViewModel", "GameViewModel destroyed!") } } -
Definition of ViewModelProvider
During configuration changes such as screen rotations, UI controllers such as fragments are re-created. However,
ViewModelinstances survive. If you create theViewModelinstance using theViewModelclass, a new object is created every time the fragment is re-created. Instead, create theViewModelinstance using aViewModelProvider.Important: Always use
ViewModelProviderto createViewModelobjects rather than directly instantiating an instance ofViewModel.private lateinit var viewModel: GameViewModel viewModel = ViewModelProvider(this).get(GameViewModel::class.java)-
ViewModelProviderreturns an existingViewModel, otherwise creates a new one. -
ViewModelProvidercreates aViewModelinstance in the given scope (ActivityorFragment).
-
-
Definition of ViewModelFactory
A
ViewModelFactoryinstantiatesViewModelobjects, with or without constructor parameters.In this example, you want a
ViewModelto hold the score, and you will pas in the score value during theViewModelinitialization.Factory method pattern that uses factory methods to create objects.
class ScoreViewModel(finalScore: Int) : ViewModel() { // The final score var score = finalScore init { Log.i("ScoreViewModel", "Final score is $finalScore") } }class ScoreViewModelFactory(private val finalScore: Int) : ViewModelProvider.Factory { override fun <T : ViewModel?> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(ScoreViewModel::class.java)) { return ScoreViewModel(finalScore) as T } throw IllegalArgumentException("Unknown ViewModel class") } }// code for sending score, which is put into ScoreViewModel as a parameter val action = GameFragmentDirections.actionGameToScore() action.score = viewModel.score NavHostFragment.findNavController(this).navigate(action) }private lateinit var viewModel: ScoreViewModel private lateinit var viewModelFactory: ScoreViewModelFactory viewModelFactory = ScoreViewModelFactory(ScoreFragmentArgs.fromBundle(arguments!!).score) viewModel = ViewModelProvider(this, viewModelFactory).get(ScoreViewModel::class.java)
Homework
- To avoid losing data during a device-configuration change, you should save app data in which class?
ViewModelLiveDataFragmentActivity
- A
ViewModelshould never contain any references to fragments, activities, or views. True or false?- True
- False
- When is a
ViewModeldestroyed?- When the associated UI controller is destroyed and recreated during a device-orientation change.
- In an orientation change.
- When the associated UI controller is finished (if it’s an activity) or detached (if it’s a fragment).
- When the user presses the Back button.
- What is the
ViewModelFactoryinterface for?- Instantiating a
ViewModelobject. - Retaining data during orientation changes.
- Refreshing the data being displayed on the screen.
- Receiving notifications when the app data is changed.
- Instantiating a