Get to Know About Android Activity Lifecycle
The most important thing as we learn to code Android apps is to know about what Activity is. We have to get to know all about Activity in Android before we go deep down in developing the app. Why? Because the first thing we will create is Activity, so it is a core fundamental that is mandatory for every developers.
What is Activity?
Activity is the screen on Android that responsible for handling user’s operations and interactions. So I will say as simple as that. Consider it like a screen. So basically, an app can have many activities inside it.
We will create a simple application that will help you understand about the Activity, starting and stopping activity, and handle the configuration changes of the activity.
If you haven’t set up the Android Studio in your computer, you have to set it up first before we begin. For tutorial about getting started with Android Studio you may go here.
Note: In this post I used Android Studio 3.2.1 so the appearance might or might not be similar like yours and it’s okay though, but make sure you use the latest Android Studio, or if you already install it, be sure to check the latest update. The Kotlin version that I used is Kotlin 1.3.11.
Getting Started
We’re gonna create a simple app for this tutorial. It is a very very simple number counter app to increment a number. I know it’s silly and what’s the point. It just a practice just to get you familiar about the Activity in Android. Open your Android Studio and you will see dialog like this and choose Start a new Android Studio Project.
Create Android Project
In the next screen will display dialog like this.
You can give the application name whatever you want but here I give the app name AwesomeCounter. After you complete all of the app creation steps, you can run the app and you will get a Hello World text as always.
Android Activity Lifecycle
The next thing that is super cool to understand is Android Activity Lifecycle. From your app here we will learn together about how the Android Activity behaves. Let’s take a look at diagram below.
Each activity will have the lifecycle like the diagram above. Okay I will talk about them one by one.
onCreate()
This method is called whenever user start an activity, the Android OS will called this first. This is the place where you can initialize UI elements and objects. Note that when the activity enter this state, it is still not visible to the user. It will be followed by onStart()
method next which will display the UI element to the user.
onStart()
In this method activity will begin presenting something to the user such as the UI elements or some contents, animations, etc. The activity will be visible to the user.
onResume()
Called right after the onStart()
method which is a very good place to resume the user’s interaction such as resuming playback video, loading latest data, etc.
onPause()
When user navigate to another activity or minimize the app, it will called this method. The activity will enter the paused state and this is a good place to handle something like stopping animations or pausing video playback. It will be followed by onStop()
and become hidden.
onStop()
Called after onPause()
and this is a good place where you can save the data. In this state the activity becomes hidden to the user but it is still exist in memory unless the device run out of memory and onDestroy()
will be called. If user navigate back in activity it will continue to onRestart()
onRestart()
This method will be called right after user navigate back to the activity from onStop()
method, it means you can write some code or logic to prepare your app to restart the data or maybe the content, UI, etc. After this state, it will call the onStart() method.
onDestroy()
This will be called after the onStop()
method. This will be triggered automatically by the device when its memory is low and need to free the memory, or manually by user by calling method like finish()
. In this state the activity will be completely hidden to the user and will be released from memory.
Okay I think that’s enough for the theory and we can now begin to implement it. Follow along with me. Open the MainActivity.kt and you will find the default onCreate()
method in it like this.
import android.support.v7.app.AppCompatActivity import android.os.Bundle class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } }
Okay first I will explain to you about this piece of code.
- Class MainActivity is the place where you implement the Activity’s behavior or lifecycle. So in order to do that it must extend the existing Activity class or its subclasses. In this case is the AppCompatActivity class.
- setContentView(layoutId) is a method from the Activity class to set which layout that we will use for this Activity. Of course for now we still have one single layout file and it is activity_main.xml and you can find it inside res/layout directory. In code you will have to write it R.layout.activity_main without the xml extension behind it.
Adding the Lifecycle Methods
Add this code below the Bundle import code.
import android.util.Log
Then below the onCreate()
, add these following methods.
override fun onStart() { super.onStart() Log.i("lifecycle", "started") } override fun onResume() { super.onResume() Log.i("lifecycle", "resumed") } override fun onPause() { super.onPause() Log.i("lifecycle", "paused") } override fun onStop() { super.onStop() Log.i("lifecycle", "stopped") } override fun onRestart() { super.onRestart() Log.i("lifecycle", "restarted") } override fun onDestroy() { Log.i("lifecycle", "destroyed") super.onDestroy() }
Instead of typing all of the above codes one by one manually, you can use the code suggestion generation from Android Studio. It will intelligently show the suggestions as you type the code like this.
If the suggestion doesn’t show up, you can open it manually by pressing Ctrl + Space key from keyboard. It also doesn’t just showing the suggestion, it also help you to import the required package for our app automatically. Ha, very convenient! After you type all of above codes, your code will be like this.
The code Log.i()
is for displaying a log or a message for us to know what event or something going on from inside our app, in this case we log out each state of the activity so we will know its current state. Let’s run the app and after it launch please check the log in the Logcat from Android Studio.
At the first launch, we will get three lifecycle logs from our app and it comes from onCreate()
, onStart()
, and onResume()
consecutively.
If we minimize our app, it will display two more logs from onPause()
and onStop()
like image below. It means our app is hidden from user but it is still inside the memory.
When you try to open app again, it will become visible again to the user and you will get three more logs from onRestart()
, onStart()
, and onResume()
like this.
The last thing is try to close or exit the app and you will get the logs just like when you minimize it but with additional log in the end which is onDestroy()
. This means your app is released from the memory.
Further Practice
Now we understand how the activity state or lifecycle works, we will try another practice here. We’re about to create a simple number counter in this app using some kind of timer. We will display an increasing number every second. Let’s open the activity_main.xml file from inside res/layout directory. In the bottom side, choose the Text tab instead of Design tab. We will code for this layout manually.
For most applications, the default will use the ConstraintLayout for layout file. For now we won’t use that because it will confuse you when still learning. So we will use the basic layout instead. Replace the entire code in this layout for this code below:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tvNumberCounter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="50sp" android:textStyle="bold" tools:text="0" /> </RelativeLayout>
The point is we’re gonna display a single TextView in the center of the screen to display the increasing number. The root layout will be a RelativeLayout. Don’t forget to give the TextView an id because it will be used from our Activity class, I give the id tvNumberCounter.
Now open MainActivity.kt file and add these following imports.
import android.os.Handler import kotlinx.android.synthetic.main.activity_main.*
Then add these variable declaration and initialization inside the MainActivity class.
// initialization of number variable var number: Int = 0 // initialization of handler val handler: Handler = Handler() // initialization of runnable for our handler val runnable = object: Runnable { override fun run() { // increase the number number++ // update the displayed number tvNumberCounter.text = "$number" // run the timer again handler.postDelayed(this, 1000) } }
After that modify the onResume()
and onPause()
method like this.
override fun onResume() { super.onResume() Log.i("lifecycle", "resumed") // start the timer handler handler.postDelayed(runnable, 1000) } override fun onPause() { super.onPause() Log.i("lifecycle", "paused") // pause or stop the timer handler handler.removeCallbacks(runnable) }
Here I will explain what are happening here:
- We use variable number which type is Integer to hold our increasing number data. This variable will be mutated every second so we must use var keyword to declare it.
- The Handler is like a thing that can handle task from us and we use it as a timer in this case and the task that will be executed is called Runnable. So we execute a certain task inside Runnable and we repeat it every second or every 1000 millisecond.
- Inside Runnable we increase the number by one using
number++
code and display it to our TextView that we created inside activity_main.xml. To access it we just simply call the id. We usetvNumberCounter.text = “$text”
to update the text. - After that we’re gonna repeat the process every second by calling this
handler.postDelayed(this, 1000)
- Inside
onResume()
is just the code to start the Handler and insideonPause()
is for stopping the Handler.
You can now run the app again, let’s see our code in action.
Very nice! Our app is working perfectly and it is counting every second. If you try to minimize it, the timer will also stopped and will start again as you open the app again. Hmm, but there is one more problem, you may try rotating the device to landscape orientation but make sure you have Auto-rotate screen turned on from the Device Settings. So what see? Yes, the number is reset to 1 again instead of continue the counter. It really is annoying right.
Handling Screen Orientation Changes
Handling the screen orientation is really simple. Okay let’s get to the point. Open the AndroidManifest.xml file and locate this code:
<activity android:name=".MainActivity">
Replace above code to this:
<activity android:name=".MainActivity" android:configChanges="orientation|screenSize">
Head over back to MainActivity.kt and add this following method inside our class.
override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) }
Now run the app and it will works correctly now between screen orientation changes.
Where to go next?
You can download this entire code from my Github repository here as I will try to put each of my tutorials there. In the next post I’m gonna talk about a simple functionality of Android app to display images, text, and button so stay tuned. Hope you like my post and share it!