Android Framework manages the life-cycle of activity and fragment , whenever there is configuration changes such as screen rotation or applying/toggling dark mode then the framework decides to recreate and any transient Ui-related data you store in them will be lost .
Save and Restore Data On Configuration Change
For simple data, the activity can use the onSaveInstanceState() method and restore its data from the bundle in onCreate(), but this approach is only suitable for small amounts of data that can be serialized then deserialized, not for potentially large amounts of data like a list of users or bitmaps ViewModel is best suitable save and restore large anount of data .
ViewModel LifeCycle
The above diagram illustrates the various life-cycle states of an activity as it undergoes a rotation and then is finished and the ViewModel which is associated with the activity will exist until the activity is fully destroyed .
Gradle
file: build.gradle(app)
dependencies { implementation "android.arch.lifecycle:extensions:1.1.1" annotationProcessor "android.arch.lifecycle:compiler:1.1.1" }
LiveData
LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the life-cycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active life-cycle state.
Activities and fragments safely observe LiveData objects and not worry about leaks activities and fragments are instantly unsubscribed to livedata when their lifecycles are destroyed.
The advantages of using LiveData
- Ensures your UI matches your data state
- No memory leaks
- No crashes due to stopped activities
- No more manual lifecycle handling
- Always up to date data
- Proper configuration changes
- Sharing resources
Create LiveData objects
LiveData is a wrapper that can be used with any data, including objects that implement Collections,
such as List. A LiveData object is usually stored within a ViewModel object
Inside Your ViewModel declare and initialize viewmodel
var myRandomNumber = MutableLiveData<String>().apply { value = (0..10).random().toString() }
Observer LiveData Changes .
Generally, LiveData delivers updates only when data changes, and only to active observers(Activities or fragments) . Inside the onCreate method of activity call observe on livedata which defined inside the viewmodel.
mainActivityViewModel.myRandomNumber.observe(this, Observer { textview.text = it })
In this tutorial we will see a simple example , where we will generate random number inside the onCreate method and set it to textview and when the device is rotate the random value should not change , also we will have button widget and inside the onclick listener of button make changes to livedata which is defined inside viewmodel , change in livedata notifies the observe(Activity) and upadte UI with newly changed value
ViewModel
- Create a MainActivityViewModel by extending ViewModel class .
- Define a LiveData by wrapping to the String data variable .
- Add createRandomNumber which modifies the livedata , when will be called on button click event .
package com.tutorialsbuzz.viewmodelsample import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import java.util.concurrent.atomic.AtomicInteger class MainActivityViewModel : ViewModel() { val TAG: String = MainActivityViewModel::class.java.simpleName var myRandomNumber = MutableLiveData<String>().apply { value = (0..10).random().toString() } fun createRandomNumber() { Log.d(TAG, "createRandomNumber"); myRandomNumber.value = (0..10).random().toString() } override fun onCleared() { super.onCleared() Log.d(TAG, "onCleared"); } }
XML Layout
Create XML Layout activity_main.xml , this will be set as content view for launcher Activity (MainActivity.kt) and add TextView and Button to your layout file
file : activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:id="@+id/tvNumber" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:gravity="center" android:text="" android:textSize="30sp" /> <Button android:id="@+id/update" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="30dp" android:gravity="center" android:text="update" android:textSize="30sp" /> </LinearLayout>
MainActivity
- Create a koltin class MainActivity.kt and extend it to AppCompatActivity class .
- Override onCreate function and set the content of this MainActivity with above defined xml layout (activity_main.xml).
- Setup the activity with the above define MainActivityViewModel .
- Set the random number to TextView .
- On Button click call createRandomNumber method of MainActivityViewModel .
file : MainActivity.kt
package com.tutorialsbuzz.viewmodelsample import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val mainActivityViewModel = ViewModelProviders.of(this).get(MainActivityViewModel::class.java) mainActivityViewModel.myRandomNumber.observe(this, Observer { tvNumber.text = it }) update.setOnClickListener({ mainActivityViewModel.createRandomNumber() }) } }
Portrait
|
Landscape
|
|
|
Observe LiveData Changes :
No comments:
Post a Comment