ViewModel With SavedState in Android
Last Updated :
25 Aug, 2021
Google launched Android Jetpack at Google I/O 2018, which is a bundle of components, tools, and guidelines for creating excellent Android apps. It included LiveData, ViewModel, Room Database, Work Manager, and other components. ViewModel will be discussed in this blog. In the Activity lifecycle, ViewModel maintains UI-related data. It enables the App to withstand configuration changes (like Screen rotation).
ViewModels are mostly used for,
- Prepare data for the user interface layer.
- Handles app rotation configuration.
Image 1, View Model Lifecycle.How to Add a ViewModel
Kotlin
class gfgViewModel : ViewModel() {
val courses = MutableLiveData<List<courses>>()
fun getCourses(): LiveData<List<courses>> {
return courses
}
private fun loadCourses() {
courses.value = // courses provided by gfg
}
}
Then to import the data into View,
Kotlin
class GeeksActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Starting the model
val gfgSampleModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
gfgSampleModel.getCourses().observe(this, Observer<List<courses>>{ courses ->
// do something like UI update
})
}
}
We must initialize the ViewModel in the View (Activities/Fragments) by using,
Kotlin
val gfgSamplemodel = ViewModelProviders.of(this).get(GeeksModel::class.java)
Now we can see the data in the UI:
Kotlin
gfgModel.getCourses().observe(this, Observer<List<Courses>>{ courses ->
// Do something here
}
This is how ViewModel is used in our Views. More information about ViewModel may be found here. Now we can change, but it's restricted. To manage that, we may use onSaveInstanceState() to return to the previous state.
Every Android application operates in its own Linux process, which is described as System Initiated Process Death. This process is started by the program when part of its code has to be executed, and it will continue to run until it is no longer required and the system needs to recover its memory for usage by other applications.
GeekTip: If your program is not in the forefront, the system can stop it at any time to free up system RAM for other processes to use.
- Both configuration and system-initiated process death may be handled by the onSaveInstanceState() bundle.
- However, it can only hold a limited amount of data and is highly dependent on speed and storage because serialization requires a large amount of memory to store the data.
- Serialization occurs on the main thread, thus when the configuration changes, the UI screen may be blocked, and the app may also freeze of produces (ANRs), i.e. App Not Responding.
- onSaveInstanceState() can only save a small amount of data.
Saved State of ViewModel
Because UI data is always referenced from ViewModel of Architecture Components and not the View (Activity/Fragment), Saved State of ViewModel may be regarded as a substitute for onSaveInstanceState(). So we'll have to perform some code to utilize onSaveInstanceState().
So, as part of Jetpack, Google launched Saved State, which allows us to retain and recover data from the saved states after it has been killed by the System Initiated Process Death.
GeekTip #2: It should be noted that the state must be basic and lightweight. Local persistence should be used for complicated or big data sets.
Add the following code to your build to integrate the Saved State in Project.
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-alpha01'
How Do I make use of Saved State?
Replace the following code snippet in the onCreate() function of your View (Activity/Fragment).
val model = GeeksViewModel.of(this, savedVMState(this)).get(MainGfGViewModel::class.java)
instead of:
val gfgModel= GeeksViewModel.of(this).get(MainGfGViewModel::class.java)
Furthermore, in ViewModel:
class GeeksViewModel(private val state: SavedStateHandle) : ViewModel() { ... }
As you can see, we supplied SavedStateHandle to the ViewModel's main function Object() { [native code] }. To obtain a SavedStateHandle, we use SavedStateVMFactory() as the Factory in our ViewModelProviders.of.
GeekTip #3: A Factory is an Interface that instructs the ViewModel on how to construct the ViewModel.
Do note that it is just a key-value pair. Even if the program dies due to System Initiated Process Death, the data will still be saved.
As you can see, we supplied SavedStateHandle to the ViewModel's main function Object() { [native code] }. To obtain a SavedStateHandle, we use savedVMState() as the Factory in our GeeksViewModel.of.
A Factory is an Interface that instructs the ViewModel on how to construct the ViewModel.
- Even if the program dies due to System Initiated Process Death, the data will still be saved.
- SavedStateHandle is similar to SharedPreferences in Android in that it operates on a Key-Value pair.
- Let's take a look at an example: we'll be creating an app with three UI components (EditText, Button, and TextView).
- When the user enters their username in the EditText and clicks the Button, the username should be displayed in the TextView
The MainViewModel should now look like this,
Kotlin
class GeeksVM(private val savedStateHandle: SavedStateHandle) : ViewModel(), BaseViewModel {
override fun getCoursename(): LiveData<String> {
return savedStateHandle.getLiveData(Constants.COURSE)
}
override fun saveCourse(username: String) {
savedStateHandle.set(Constant.COURSE, course)
}
}
Here,
- The data is stored using savedStateHandle.set("Key","Value").
- The saved state handle.get live data("key") method is used to retrieve the LiveData of the String datatype.
The MainViewModel class implements the BaseViewModel, which looks like this.
Kotlin
interface gfgViewModel {
fun getCoursename(): LiveData<String>
fun saveCourse(username: String)
}
To Validate
Perform Step - #1 and you will not see your app's package name in the console.
When you re-open the program, you should see the output persisted and shown in the TextView of the Screen.
Important Notes:
If you wish to preserve the data, use savedState.
savedStateHandle.set("key_name","value")
If you wish to retrieve data from a savedState, use the following syntax:
savedStateHandle.get("key_name")
Use if you wish to obtain LiveData as a return type.
savedStateHandle.getLiveData("key_name")
If you want to see if a certain key is present in savedState, use the following code.
savedState.contains("key_name")
If you want to locate all the keys in the savedState, use the following to get a list of them.
savedState.keys()
You may also remove any individual value by accessing it via its key. To carry out the following action:
savedState.remove("key_name")
Similar Reads
Shared ViewModel in Android
In Android development, ViewModel serves as a means to facilitate data sharing among different fragments or activities. By utilizing the same ViewModel across multiple fragments, each fragment gains access to the shared data and functionality encapsulated within the ViewModel. This approach offers a
4 min read
Data Binding with ViewModel in Android
DataBinding is one of the most important concepts to really improve the performance of your Android Application It plays a vital role in the maintenance of the many Android Architectures. In this article, we will learn about DataBinding in ViewModel In Android. Benefits of integrating Data binding i
5 min read
View Recycling in Android with ListView
Memory management is a crucial aspect of app development. Since mobile devices have very limited memory, it is necessary to use it carefully in our applications. One of the best practices involved in doing so is "view recycling". This article is about view recycling in Android and then a simple app
4 min read
Android ListView in Java with Example
A ListView in Android is a type of AdapterView that displays a vertically scrollable list of items, with each item positioned one below the other. Using an adapter, items are inserted into the list from an array or database efficiently. For displaying the items in the list method setAdaptor() is use
3 min read
How to Save Switch Button State in Android?
In Android, a Switch is a type of button that lets the user toggle between two actions or instances. In general, a Switch is used for selecting one between two options that can be invoking any actions or functions. In this article, we are going to see how we can save the state of the Switch Button i
3 min read
ViewAnimator in Android with Example
ViewAnimator is a very fascinating and useful feature as it switches between two or more views smoothly and mainly meant for animation features of the views on screens. It is the parent class of ViewFlipper and ViewSwitcher and the main distinction is it can switch between more than 2 views also. It
4 min read
Data Binding in Android with Example
In Android, the Data Binding Library is a support library that allows you to bind UI components in your layouts to data sources in your app using a declarative format rather than programmatically.Step by Step Implementation:Step 1: Create a New ProjectIf you donât know how to create a new project in
2 min read
Android - Move Views Out of The Way with Kotlin
We have seen many views within our android application that change their position with respect to other views to adjust them within the screen. We can get to see when we are displaying a snack bar along with the Floating action button. When the SnackBar is displayed the floating action button is sli
3 min read
SearchView in Android with RecyclerView
Many apps represent data in the form of huge lists and for filtering these lists we have seen the SearchView present inside these apps. So for filtering this list of data we generally use a SearchView. In this article, we will take a look at the implementation of Search View in Android with a Recycl
10 min read
Data Binding with LiveData in Android
Data Binding is a feature which help us to bind UI components with data sources in an Android application using a declarative format. So, Why we are using Data binding with LiveData? Actually, If we want our views to directly communicate with ViewModel (Data source), we can do that simply without us
3 min read