Android Activity Lifecycle Explained: Enhance Your App's Navigation
Explore expert techniques to enhance Android app navigation using Activity Lifecycle insights.
Activity
Single UI-Screen present to the user.
Different events, some user-triggered and some system-triggered can cause an Activity to transition from one state to another.
As a user navigates through the application, the Activity instances in our app transition through different states in their lifecycle. The Activity class provides several callbacks that let the activity know when a state changes or that the system is creating, stopping, or resuming an activity or destroying the process the activity resides in.
Within the lifecycle callback methods, we can declare how the activity behaves during such state transition.
The Activity class provides us with a set of six callback methods, which are invoked by the activity based on the state transition of the activity:
onCreate()
activity is created.
this is where we create views, bind data to lists, instantiate class-scope variables & call the
setContentView()
method to define the activities layouts.receives the parameter
savedInstanceState
, which is aBundle
object containing the activity's previously saved state. If the activity has never existed before, the value of the object is null.passes to
onStart()
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) }//Eg - Music App UI Created
onStart()
activity becomes visible to the user.
override fun onStart(){ super.onStart() }//Eg - Music App UI Visible to User
onResume()
invoked just before the activity starts interacting with the user
activity comes at the top of the activity stack
and implements most of the app's functionality
override fun onResume(){ super.onResume() }//Invoked after onStart()
onPause()
invoked when activity loses focus & enters a paused state
activity remains partially visible
passes to
onStop()
oronResume()
methods depending on the transitionoverride fun onPause(){ super.onPause() }//Eg - Call Received //Invokes onResume when call declined
onStop()
invoked when activity is no longer visible to the user
passes to onDestroy() or
onRestart()
methodonRestart()
method is invoked when an activity in a stopped state is about to restart & it restores the state of the activity. Followed byonStart()
.override fun onStop(){ super.onStop() }//Eg - Invoked when call accepted //moves to onRestart() when call ends
onDestroy()
invoked when activity is destroyed.
override fun onDestroy(){ super.onDestroy() }//Invoked when application closed
Demonstration of an Activities Lifecycle
As we run our Application :
The
onCreate()
,onStart()
,onResume()
method for the main activity are invoked in order.When the button to go to the second activity is pressed:
the
onPause()
method for main activity is invokedthe
onCreate()
,onStart()
,onResume()
method for the second activity are invoked in order.the
onStop()
method for main activity is invokedWhen the button to go to the main activity is pressed:
the
onPause()
method for the second activity is invokedthe
onCreate()
,onStart()
,onResume()
method for the main activity are invoked in order.the
onStop()
method for the second activity is invokedWhen the Orientation of the main activity is changed or a Multi-Window mode is enabled by the user:
the
onPause()
,onStop()
,onDestroy()
,onCreate()
,onStart()
,onResume()
method for the main activity are invoked in order, and the new instance of the activity is createdHowever as the activity is re-created, the data inputted in the main activity is lost . Hence, considering data-saving and implementing callback methods properly is a must. Data may also be lost when our MainActivity is destroyed from the back stack by the OS to free some space.
Creation of Activity Switching :
val countText : TextView = findViewById(R.id.countText)
val incrementBtn : Button = findViewById(R.id.incrementBtn)
val changeBtn : Button = findViewById(R.id.changeBtn)
//helps us handle the textView & our button in the MainActivity.kt
incrementBtn.setOnClickListener{
//lambda function in the Button class enabled when button clicked
countText.text = "${countText.text.toString().toInt()} + 1"
//increment text
}
changeBtn.setOnClickListener{
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
//starts an intent that switches context to SecondActivity.kt
}
Coming Back to our MainActivity, after incrementing the countText value to a certain value and then heading to the SecondActivity.
However changing the orientation of our device leads to loss of data as the MainActivity
is recreated.
Dealing with data loss :
- Using the
onSaveInstanceState()
method, which is a lifecycle method in Android used to save temporary state data of an activity before it is destroyed. The saved state is stored in aBundle
object, which can later be retrieved to restore the data when the activity is recreated.
Save the data using the
onSaveInstanceState(Bundle)
method.Retrieve the saved data using the
onCreate(Bundle)
method or theonRestoreInstanceState(Bundle)
method.
// Restore data if available
if (savedInstanceState != null) count = savedInstanceState.getInt("count", 0)
countText.text = count.toString()
incrementBtn.setOnClickListener {
count++
countText.text = count.toString()
}
// Save data before activity is destroyed
// called before onStop() or onPause(), if the activity is getting destroyed
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("count", count)
}
Using
ViewModel
class from Android Jetpack which helps retain data across configuration changes without relying on lifecycle methods.Using
Persistent Storage
for data that needs to persist beyond app restarts or user sessions, eg: database, or a file, etc.
Tasks & Backstack
A task is a collection of activities that the user does.
These activities are arranged in a stack called the back stack in the order in which each activity is opened, which operates as a last-in-first-out data structure.
Hence, when the user taps back, the activities are popped from the back stack.
In the above example, when the user presses the app icon on the device, a new task is created, and the following application's main activity is put in the back stack.
Opening further activities on the application leads them too on the back stack, however as the user navigates on the back button, the topmost activity is popped off.