How to Restore Data on Configuration Changed in Android using Bundles?
In Android, if the configuration of the application changes, for example when the android screen is rotated, then some data is lost and reset. Especially, the data from the variables. So this issue can be solved by overriding the functions onSaveInstanaceState() and onRestoreInstanceState(). So in this article, it’s been discussed how this issue can be resolved in detail using the flow chart, so as to understand when these above functions are called. Note that we are going to implement this project using the Kotlin language.
Below is a flow chart represents how the methods are called and data is restored and updated in the UI:
Step by Step Implementation
Step 1: Create an empty activity project
- Using Android Studio create a new empty activity Android Studio project. Refer to Android | How to Create/Start a New Project in Android Studio?, to know how to create an empty activity Android Studio project.
Step 2: Working with the activity_main.xml file
- The main layout of the application containing EditText, and one TextView, and two Buttons, which increment and decrement the value of the TextView.
- To implement the UI invoke the following code inside the activity_main.xml file.
XML
<? xml version = "1.0" encoding = "utf-8" ?> < androidx.constraintlayout.widget.ConstraintLayout android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".MainActivity" tools:ignore = "HardcodedText" > < EditText android:id = "@+id/editText" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_marginStart = "16dp" android:layout_marginTop = "32dp" android:layout_marginEnd = "16dp" android:hint = "Enter Something" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toTopOf = "parent" /> < Button android:id = "@+id/decrementB" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginStart = "32dp" android:layout_marginTop = "32dp" app:icon = "@drawable/ic_remove" app:iconGravity = "textStart" app:iconPadding = "0dp" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toBottomOf = "@+id/editText" /> < TextView android:id = "@+id/counterText" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "0" android:textSize = "24sp" app:layout_constraintBottom_toBottomOf = "@+id/incrementB" app:layout_constraintEnd_toStartOf = "@+id/incrementB" app:layout_constraintHorizontal_bias = "0.497" app:layout_constraintStart_toEndOf = "@+id/decrementB" app:layout_constraintTop_toTopOf = "@+id/incrementB" /> < Button android:id = "@+id/incrementB" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginTop = "32dp" android:layout_marginEnd = "32dp" app:icon = "@drawable/ic_add" app:iconGravity = "textStart" app:iconPadding = "0dp" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintTop_toBottomOf = "@+id/editText" /> </ androidx.constraintlayout.widget.ConstraintLayout > |
Output:
Step 3: Working with the MainActivity.kt file
- In the MainActivity,kt file the two functions onSaveInstanceState(outState: Bundle) and onRestoreInstanceState(savedInstanceState: Bundle) has to be overridden, the onSaveInstanceState function puts the data to bundle named outState, and onRestoreInstanceState function receives the data using Bundle named savedInstanceState. Refer to the flow chart provided above to get clear flow.
- To implement the same invoke the following code inside the MainActivity.kt file.
- Comments are added inside the code to understand the code in more detail.
Kotlin
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.EditText import android.widget.TextView class MainActivity : AppCompatActivity() { // instances of all the UI elements lateinit var editText: EditText lateinit var counterText: TextView lateinit var incrementB: Button lateinit var decrementB: Button // counter to increment or // decrement the counter text var countInt: Int = 0 override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_main) // register all the UI elements with // their appropriate IDs editText = findViewById(R.id.editText) incrementB = findViewById(R.id.incrementB) decrementB = findViewById(R.id.decrementB) counterText = findViewById(R.id.counterText) // handle the increment button incrementB.setOnClickListener { if (countInt >= 0 ) { countInt++ counterText.text = countInt.toString() } } // handle the decrement button decrementB.setOnClickListener { if (countInt > 0 ) { countInt-- counterText.text = countInt.toString() } } } override fun onSaveInstanceState(outState: Bundle) { super .onSaveInstanceState(outState) // put the unique key value with the data // to be restored after configuration changes outState.putInt( "counterData" , countInt) } override fun onRestoreInstanceState(savedInstanceState: Bundle) { super .onRestoreInstanceState(savedInstanceState) // get the stored data from the bundle using the unique key countInt = savedInstanceState.getInt( "counterData" ) // update the UI counterText.text = countInt.toString() } } |