Activities are a vital part of Android. An Activity provides a window in which your application draws the Views that form your UI. Simply put, an Activity implements a single screen in your app. It's an essential building block that you've probably created in Android Studio before.
In this topic, you will get familiar with Activities. You'll learn about the Activity lifecycle and how to switch from one Activity to another.
Creating an Activity
Let's start by creating an Activity.
To do this, open a project in Android Studio, right-click your java/your.project.name or res/layout folder, and then click New → Activity → Empty Activity. There's a bunch of different Activity templates, but Empty Activity allows you to make everything from scratch.
A New Android Activity window will pop up. Be sure to keep the Generate a Layout File checkbox ticked in case you need a UI for this Activity. Customize the Activity Name and hit the Finish button:
Android Studio will build your project, and you will see a Kotlin file containing your new Activity. You can now switch to the new layout XML file and add something to your UI if you wish. If you're not familiar with layouts, you can learn more about them in the XML Layouts in Android topic.
Activity lifecycle
As your app is used, the Activity switches between different lifecycle states. Lifecycle callback methods enable you to control what happens when a user leaves or reopens your app. For example, imagine you're creating a game. So players don't lose their progress, you can automatically pause the game and its sound when they receive a call or switch to another app. By correctly implementing lifecycle callbacks, you will also avoid potential problems like app crashes and data loss.
Some key lifecycle methods are described below:
onCreate(): called when the system initializes the Activity for the first time (before it becomes visible). In this method, you declare your Activity's UI usingsetContentView(), makefindViewById()calls, and define other things that should only happen when the Activity is created. This method also receives asavedInstanceStatebundle that contains the Activity's previous state and data — something you'll learn more about later in this topic.onStart(): this method is called afteronCreate(). The system now prepares to make the Activity visible and interactive. There's usually no reason to override this method.onResume(): the Activity becomes visible and ready to interact with the user. The application stays in this state until something interrupts it: a phone call, the screen turning off, user switching to another activity and so on. You can use this method to resume everything that should only work when the Activity is visible. If it's interrupted, theonPause()method is called.onPause(): this method is either called when the Activity is about to stop or when it's no longer in the foreground. The Activity might still be visible in multi-window mode, though. In this case, you may want to continue updating the UI, so be careful with this method. Don't use it to save data: it needs to be fast because an Activity can't be resumed without pausing the previous one, which could cause data loss. Instead, useonStop()to save things you need. You might want to release different sensors in this method, but it can also be done in theonStop().onStop(): called if the user can no longer see your Activity. This happens even if the user switches between different Activities in the same app if they cover the entire screen. You can perform intensive actions here, like saving data or releasing different sensors (camera, GPS, etc.). Android automatically saves the state of each View object (if it has an ID), so you don't have to worry about restoring this data if the user decides to return to your Activity again. After this method, the system either invokesonRestart()if the user switches back to your Activity oronDestroy()when the system or user decides to kill the app or Activity.onRestart(): fired when the Activity is about to restart after theonStop()method. Restores the Activity from the moment it was stopped.onStart()is then called again.onDestroy(): this method is called when the Activity is about to be destroyed. There are different reasons this might happen: the system doesn't have the resources to keep your app running, the user presses the "Back" button, etc. If user rotates the screen, activity will also be destroyed: the system does this so that your application can reload resources based on the new configuration. If you haven't released some resources in theonStop()method, you should release all resources in this callback — files, internet connections, async operations, and so on.
Earlier, you learned that onCreate() accepts savedInstanceState as a parameter. This is a Bundle object containing data about the Activity's state before it was destroyed. If it's the first time the Activity has been created, the savedInstanceState will be null. It's important to save data entered by the user in this object to avoid losing it if the Activity is destroyed. But don't save files, media, or anything your app can cache or reload from the servers or databases.
You can see an example of how to use savedInstanceState below:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Get data if it's not the first time Activity is created
if (savedInstanceState != null) {
timerTextView.text(savedInstanceState.getString("timerCount"))
}
}
// Saving data before Activity is destroyed
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("timerCount", timerTextView.text.toString())
}That's it!
Switching Activities
When you have two or more Activities, you need to know how to switch between them. Let's use the two simple screens shown below as an example:
Intents will help us with this task. We need to make the OPEN SECOND ACTIVITY button do something: in this case, it will be firing an Intent to open the SecondActivity. Let's set an onClickListener for this button in the MainActivity.kt:
openSecondActivityButton.setOnClickListener {
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}Intent constructor asks us to pass a Context as a first parameter. A Context is an abstract class whose implementation is provided by Android, as Android Documentation states. It provides access to app resources, assets, and so on. Because Activity extends from Context, we can use this as an argument in this Intent.
Here's what we'll see after running the app:
Now let's apply the same approach to the OPEN MAIN ACTIVITY button on the SecondActivity:
openMainActivityButton.setOnClickListener {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}The final result is shown below:
It works, but it's far from perfect. Every time one of these buttons is pressed, a new Activity is created, and you can't navigate away from it with a single click of the "Back" button. That's not good for user experience or device RAM. To avoid this problem, we can change the behavior of the OPEN MAIN ACTIVITY button so that it will destroy the current activity using finish():
openMainActivityButton.setOnClickListener {
finish() // destroys activity and returns to the previous one
}You should be aware that this solution isn't perfect either. finish() destroys the Activity, meaning the state won't be saved, leading to the loss of Activity data. You might therefore need to reenter the previous data the next time the Activity is launched. Better solutions of changing the behavior of activities are discussed in the Task and backstack topic.
Conclusion
In this topic, you've become familiar with Android Activities. You've created one, seen how to switch between them, and found out about the different stages of the Activity lifecycle. Time for some practice!