Android development foundation - Activity life cycle

Activity life cycle

return stack

Activities in Android can be stacked. Every time a new Activity is started, it will be overlaid on the original Activity, and then the top Activity will be destroyed by clicking the back button, and the next Activity will be displayed again.

Android uses tasks to manage activities. A task is a collection of activities stored in a stack, which is also called a back stack. The stack is a last-in-first-out data structure. By default, whenever a new Activity is started, it will be pushed into the return stack and be at the top of the stack. Whenever the back key is pressed or finish is called When the method destroys an Activity, the Activity at the top of the stack will be popped out, and the previous Activity that was pushed into the stack will be at the top of the stack again.

The system always displays the Activity at the top of the stack to the user.

Activity state

Each Activity may have up to four states during its life cycle.

  • Running state: When an Activity is at the top of the return stack, the Activity is in the running state. The last thing the system is willing to recycle is the Activity in the running state, because it will lead to a poor user experience.
  • Paused state: When an Activity is no longer at the top of the stack, but is still visible, the Activity enters the paused state. For example, when an Activity in the form of a dialog box is in the running state, it will not occupy all the screen space, and the Activity in the paused state is still completely alive, and the system is unwilling to recycle such an Activity because it will lead to poor user experience. Only when the memory is extremely low, the system will consider recycling this type of Activity.
  • Stopped state: When an Activity is no longer at the top of the stack and is completely invisible, it enters the stopped state. The system will still save the corresponding state and member variables for this type of Activity, but this is not completely reliable. When the memory is needed elsewhere, the Activity in the stopped state may be recycled by the system.
  • Destroyed state: After an Activity is removed from the return stack, it becomes destroyed. The system is most inclined to recycle the Activity in this state to ensure that the phone's memory is sufficient.

Activity lifetime

The Activity class defines 7 callback methods, covering every aspect of the Activity life cycle:

  • onCreate: Called when the Activity is created for the first time, the user should complete the initialization of the Activity in this method, such as loading the layout, binding events, etc.
  • onStart: This method is called when the Activity changes from invisible to visible
  • onResume: This method is called when the Activity is ready to interact with the user. At this time, the Activity must be at the top of the return stack and in the running state
  • onPause: This method is called when the system is ready to start or resume another Activity. Usually in this method, some CPU-consuming resources will be released and some key data will be saved, but the execution speed of this method should be fast, otherwise it will affect the use of the new stack top Activity
  • onStop: This method is called when the Activity is completely invisible. The main difference between it and the onPause method is that if the new Activity started is a dialog activity, the onPause method will be executed, but the onStop method will not be executed.
  • onDestroy: This method is called before the Activity is destroyed, after which the state of the Activity will become destroyed
  • onRestart: This method is called before the Activity changes from the stopped state to the running state, that is, the Activity is restarted

Among the above methods, except the onRestart method, the others are in pairs, so that the Activity can be divided into the following 3 lifetimes:

  • Complete life cycle: What the Activity experiences between the onCreate method and the onDestroy method is the complete life cycle. Generally, an Activity completes various initialization operations in the onCreate method, and completes the release of memory in the onDestroy method. 
  • Visible lifetime: What the Activity experiences between the onStart method and the onStop method is the visible lifetime. During the visible lifetime, the Activity is always visible to the user, even if it may not be able to interact with the user. Users can reasonably manage resources visible to users through these two methods. For example, resources are loaded in the onStart method, and resources are released in the onStop method, so as to ensure that the Activity in the stopped state does not occupy too much memory.
  • Foreground lifetime: What the Activity experiences between the onResume method and the onPause method is the foreground lifetime. During the lifetime of the foreground, the Activity is always running, and the Activity at this time can interact with the user

Experience the life cycle of Activity

Create a new project here, named ActivityLifeCycleTest, and allow automatic creation of Activity and layout, and then create two sub-Activities, named NormalActivity and DialogActivity respectively. Modify normal_layout to:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is a normal activity"
        />

</LinearLayout>

Modify dialog_layout as:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is a dialog activity"
        />

</LinearLayout>

The two contents are similar, both use TextView to display a line of text.

Modify the AndroidManifest.xml file to configure DialogActivity as a dialog box:

        <activity
            android:name=".DialogActivity"
            android:exported="true" 
            android:theme="@style/Theme.AppCompat.Dialog" />
        <activity
            android:name=".NormalActivity"
            android:exported="true" />

The theme of the Activity is specified above using the android:theme attribute.

Modify the activity_main layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/startNormalActivity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start NormalActivity"
        tools:ignore="DuplicateIds" />
    <Button
        android:id="@+id/startDialogActivity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start DialogActivity"/>
        

</LinearLayout>

Two buttons are added above, one for launching NormalActivity and one for launching DialogActivity.

Finally modify the code in MainActivity:

package com.example.activitylifecycletest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private val tag = "MainActivity"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(tag, "onCreate")
        setContentView(R.layout.activity_main)
        startNormalActivity.setOnClickListener {
            val intent = Intent(this, NormalActivity::class.java)
            startActivity(intent)
        }
        startDialogActivity.setOnClickListener {
            val intent = Intent(this, DialogActivity::class.java)
            startActivity(intent)
        }
    }

    override fun onStart() {
        super.onStart()
        Log.d(tag, "onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.d(tag, "onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.d(tag, "onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.d(tag, "onStop")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(tag, "onDestroy")
    }

    override fun onRestart() {
        super.onRestart()
        Log.d(tag, "onRestart")
    }
}

In the onCreate method, click events are registered for the two buttons. Clicking the first button will start NormalActivity, clicking the second button will start DialogActivity, and then override the methods mentioned above.

The result after running the program is:

 The corresponding printed information is:

2022-09-12 13:50:36.745 11707-11707/com.example.activitylifecycletest D/MainActivity: onCreate
2022-09-12 13:50:37.291 11707-11707/com.example.activitylifecycletest D/MainActivity: onStart
2022-09-12 13:50:37.295 11707-11707/com.example.activitylifecycletest D/MainActivity: onResume

 It can be seen that when MainActivity is created for the first time, the onCreate, onStart and onResume methods will be executed once, and then the first button will be clicked to start NormalActivity:

 At this time, the printed information is:

2022-09-12 13:52:34.493 11707-11707/com.example.activitylifecycletest D/MainActivity: onPause
2022-09-12 13:52:35.455 11707-11707/com.example.activitylifecycletest D/MainActivity: onStop

At this time, NormalActivity has completely covered MainActivity, so the onPause and onStop methods will be executed, and then press the Back key to return to MainActivity, and the printed information is:

2022-09-12 13:54:37.474 11707-11707/com.example.activitylifecycletest D/MainActivity: onRestart
2022-09-12 13:54:37.486 11707-11707/com.example.activitylifecycletest D/MainActivity: onStart
2022-09-12 13:54:37.488 11707-11707/com.example.activitylifecycletest D/MainActivity: onResume

Since MainActivity has entered the stop state before, it will execute the onRestart violation, and then execute the onStart and onResume methods.

Then click the second button to start the DialogActivity:

 At this time, the printed information is:

2022-09-12 13:56:23.189 11707-11707/com.example.activitylifecycletest D/MainActivity: onPause

It can be seen that only the onPause method is executed at this time. This is because DialogActivity does not completely cover the main MainActivity. At this time, MainActivity enters the pause state and does not enter the stop state.

The print information after pressing back is:

2022-09-12 13:59:24.829 11707-11707/com.example.activitylifecycletest D/MainActivity: onResume

At this time, only the onResume method is executed, and finally the printed information after pressing back to launch MainActivity is:

2022-09-12 14:00:22.132 11707-11707/com.example.activitylifecycletest D/MainActivity: onPause
2022-09-12 14:00:23.358 11707-11707/com.example.activitylifecycletest D/MainActivity: onStop
2022-09-12 14:00:23.377 11707-11707/com.example.activitylifecycletest D/MainActivity: onDestroy

According to this, the onPause, onStop and onDestroy methods will be executed, and finally MainActivity will be destroyed.

What to do if the Activity is recycled

As mentioned before, when an Activity enters the stopped state, it may be recycled by the system. And suppose there is such a scenario, there is an Activity A in the application, the user starts Activity B on the basis of Activity A, and A enters the stop state, but due to the problem of system memory, A is recycled, at this time the user presses the back returns to A, then the onCreate method will be called instead of the onRestart method to recreate Activity A for display.

The above situation seems reasonable, but if there is user-input information or processed data in Activity A, then the onCreate method will be called to rebuild after recycling Activity A and these contents will be lost, which will greatly affect the user experience. .

Activity provides an onSaveInstanceState callback method, which can guarantee that it will be called before the Activity is recycled, so this method can be used to solve this problem.

The onSaveInstanceState method will carry a parameter of Bundle type. Bundle provides a series of methods for saving data, such as putString/putInt. Each save method needs to pass in two parameters. The first parameter is a key, which is used to retrieve data from the Bundle later. value, the second parameter is the actual content to be saved.

Add the following code in MainActivity to save temporary data:

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val tempData = "Something you just typed"
        outState.putString("data_key", tempData)
    }

After the data is saved, it needs to be restored in the onCreate method. This method has a Bundle type parameter, which is generally null, but if the data is saved through the onSaveInstanceState method before the Activity is recycled by the system, the parameter will contain the previously saved All data, just need to use the corresponding value method to get the data.

        if (savedInstanceState != null) {
            val tempData = savedInstanceState.getString("data_key")
            Log.d(tag, "tempData is $tempData")
        }

After receiving the data, you can perform corresponding processing.

Guess you like

Origin blog.csdn.net/SAKURASANN/article/details/126817549