One, the introduction
Activity start process series articles are based on Android9.0 source code, so there are certain deviations with other Android versions of the source code, but the general process of Activity start is consistent with this is OK. Because the process of starting an Activity is relatively complex, the Activity start series is divided into three parts: the beginning, the middle and the end. The first part mainly explains some classes, data structures, launch modes and flags in the Intent in the process of starting an Activity. Activity in the application process and ActivityManagerService (later called AMS) process to start the source code to explain; The last chapter is mainly to explain the Activity lifecycle source code. Before we start the source code, let’s start two diagrams of the Activity.
Figure 1 is a sequence diagram of the process created after startActivity is called by the upper-layer application if the process in which the Activity is started does not exist. Figure 2 shows a sequence diagram of an Activity entering the Pause state before it is started, as well as the sequence diagram of an Activity entering the puase state from onCreate to onResume, which is not drawn because it is similar. The source code will be explained later. So let’s move on to the body of the text.
Second, the body
Before we start, here’s a question that might come up during an interview: What’s the process of clicking on the app Launcher? Here’s a quick explanation.
(1) When the user clicks an application icon on the desktop, the Launcher creates an Intent based on the Activity information on the home page of the application to be launched, and then calls the startActivitySafely method in Launcer. The Activity is then started by calling the Activity’s startActivity method.
(2) in Instrumentation through Binder call into AMS;
(3) In AMS, the basic information of the Activity to be started will be searched in PackageManagerService (hereafter referred to as PMS).
(4) Check whether the Activity exists. If so, check whether you have permission to start the Activity.
(5) Construct ActivityRecord to store the basic information of the Activity. This class is the basic unit of storing activities in AMS, which will be explained later.
(6) Determine whether the existing Activity or stack can be reused based on the launch mode and Flags value in the Intent; otherwise, create a new stack.
(7) Add ActivityRecord to the stack;
(6) Notify the Launcher interface to enter Pause state through Binder;
(8) Check whether the process in which you want to start the Activity exists. If so, use Binder to call ActivityThread to execute the lifecycle method.
(9) If not, Zygote fork a child process and create an ActivityThread object to start a UI thread. Bind ActivityThread attach method to AMS. With the Binder, the Activity is called to ActivityThread to start the Activity life cycle.
(10) After the Activity life cycle is completed, Binder calls the stop method of the previous Activity in AMS. At this point an Activity is truly started.
Here is an overview of the Activity startup process, the subsequent understanding of the source code will be of great help.
1, the LaunchMode
1.1 Startup Mode
As long as it is Android development, I want to start the Activity mode in Android is not strange, but here still have to mention, the subsequent source understanding has certain help. There are four startup modes in Android, and activities are at the top of the stack in any one of them. The four startup modes are:
(1) Stansard: Regenerates the Activity instance on the stack and pushes it to the top, regardless of whether the Activity is already started.
(2) singleTop: If the same Activity instance exists at the top of the stack as the Activity to be started, the Activity instance object at the top of the stack will be reused;
(3) singleTask: If there is an Activity instance object in the stack that is the same as the Activity to start, it will reuse the Activity instance object in the stack and remove the Activity element above the Activity;
(4) singleInstance: Create a new Task to store an Activity, and only this Activity will exist in the Task, even if there are other activities with the same stack affinity as the current Task. If the Activity instance object already exists in the Task, it is reused directly.
1.2 TaskAffinity
By default, all activities in an app have the same taskAffinity, although it is possible to specify an affinity for a particular Activity in the configuration file. If the affinity of an Activity is different from that of the current application stack, different startup modes may cause different results. The affinity of a stack is the same as the affinity of its root Activity.
(1) Standard and singleTop If you start an Activity in either mode in the singleInstance application stack, you will first check whether there is an application stack with the same affinity as the Activity to be started. If it exists, the Activity is pushed to the application stack; if it does not exist, the application stack is recreated for storage. Otherwise, starting an Activity in either mode in the application stack pushes the Activity into the current application stack.
(2) singleTask: If there is an Activity to start that has the same affinity as the application stack, the Activity first checks to see if there is an instance of the Activity in the application stack that has the same taskAffinity. If it exists, destroy the Activity above the Activity and call onNewIntent. If there is no task stack, create a new task stack and push the Activity into the stack; otherwise, move the task stack with the same affinity to the foreground and add the Activity to the task stack.
(3) singleInstance: There is only one instance of an Activity in the application stack where an Activity in this startup mode is located. Even if other activities have the same affinity with the application stack, if other activities are started in this application stack, they will first search to see if there is an application stack with the same affinity. If not, create a new application stack.
Flags in Intent
In Android, if the Activity launch mode specified in the AndroidManifest conflicts with the Flags specified in the Intent, the launch mode specified in the AndroidManifest prevails. Here will be several commonly used and in the process of reading the source code will appear part of the Flag to illustrate:
(1) FLAG_ACTIVITY_NEW_TASK: If this flag is used alone, it will first check whether there is a stack of tasks with the same affinity as the Activity being started (namely, taskAffinity. Note that activities in the same application generally have the same affinity unless an affinity is set separately for the Activity). If there is, Move the whole stack to the foreground directly, and keep the state in the stack unchanged, that is, the order of activities in the stack unchanged, and then push the started activities onto the stack, notice the difference between here and singleTask. If not, a new stack is created to hold the started activity. Combined with 4, the singleInstance effect can be achieved by clearing all activities that already exist in the stack and adding the Activity that will be launched to the stack. Combined with 3, the singleTask effect can be achieved. If this Flag is set in the Intent, the Activity started with the startActivityForResult method will receive an aborted return.
FLAG_ACTIVITY_SINGLE_TOP: FLAG_ACTIVITY_SINGLE_TOP: FLAG_ACTIVITY_SINGLE_TOP: FLAG_ACTIVITY_SINGLE_TOP: FLAG_ACTIVITY_SINGLE_TOP: FLAG_ACTIVITY_SINGLE_TOP: FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_CLEAR_TOP: If an instance of an Activity already exists in the current application stack, and the LaunchMode of the Activity to be launched is Standard, the current instance and the Activity above the instance object will be cleared anda new instance object will be created. Otherwise, the existing instance object will be reused.
FLAG_ACTIVITY_CLEAR_TASK: Clear the task stack. Use it with FLAG_ACTIVITY_NEW_TASK to clear the task stack.
FLAG_ACTIVITY_NO_HISTORY: Once an Activity exits, or another Activity is started in the Activity, it does not exist on the stack. You can also set “Android :noHistory” in androidmanifest.xml;
FLAG_ACTIVITY_MULTIPLE_TASK: it is always used in conjunction with FLAG_ACTIVITY_NEW_DOCUMENT and FLAG_ACTIVITY_NEW_TASK to create a new Task to store the Activity.
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS: Activity is not added to the list of recently started activities;
FLAG_ACTIVITY_BROUGHT_TO_FRONT: This flag is not usually set by code in the application, but is automatically set when Launch Mode is singleTask;
FLAG_ACTIVITY_LAUNCH_ADJACENT: Used in split-screen multi-window mode, the new activity will be displayed next to the activity. This flag can only be used in conjunction with FLAG_ACTIVITY_NEW_TASK.
FLAG_ACTIVITY_FORWARD_RESULT: is used to pass through results, such as when A starts B, B starts C, and C returns to A. You need to add the Flag to B’s Intent and do not use the startActivityForResult method to launch it.
FLAG_ACTIVITY_REORDER_TO_FRONT: FLAG_ACTIVITY_REORDER_TO_FRONT: FLAG_ACTIVITY_REORDER_TO_FRONT: FLAG_ACTIVITY_REORDER_TO_FRONT: FLAG_ACTIVITY_REORDER_TO_FRONT: FLAG_ACTIVITY_REORDER_TO_FRONT For example, if there are four activities in A task stack (A, B, C, D), if B is started in D, the task stack changes to A, C, D, and B. The priority of this Flag is lower than FLAG_ACTIVITY_CLEAR_TOP.
3. Store the Activity data structure class
3.1 ActivityRecord
It is the smallest unit of Activity management. The basic information about an Activity is stored in this data structure class, including the package name, ActivityInfo, startup time, owning process, and TaskRecord. Each time a new Activity is started, a new ActivityRecord object is created to store basic information about the Activity.
3.2 TaskRecord
It is a stack structure for storing ActivityRecords, otherwise known as a task stack, with the currently visible Activity at the top. An ActivityRecord is stored via an ArrayList. There are two important member variables:
// Store all ActivityRecord of the current task stack final ArrayList<ActivityRecord> mActivities; Private ActivityStack mStack; private ActivityStack mStack;Copy the code
3.3 ActivityStack
3.3.1 definition
ActivityStack is responsible for managing a stack of tasks (TaskRecords), which is a stack structure in which the elements are TaskRecords. Each Activity has a state at a specific time, such as display, destruction, etc. From the perspective of the application process, these state changes are the execution of the Activity’s life cycle function. These state changes need to be driven by ActivityStack. It determines whether a TaskRecord needs to be created before it is created, if it is created by ActivityDisPlay, and then moves the Stack to the foreground and adds it to ActivityDisPlay’s mStacks.
3.3.2 rainfall distribution on 10-12 state
The state of an Activity is defined by the Enumerated ActivityState class:
enum ActivityState {
INITIALIZING,
RESUMED,
PAUSING,
PAUSED,
STOPPING,
STOPPED,
FINISHING,
DESTROYING,
DESTROYED
}
Copy the code
3.3.3 Some member variables
ArrayList<TaskRecord> mTaskHistory: Records all activities in the rollback stack, possibly while the Activity is still running, and stores the TaskRecord object. ArrayList<TaskRecord> mLRUActivities: Sorts all activities in the current ActivityStack by least recently used (LRU). The first element in the list is the latest Activity. ActivityRecord mPausingActivity: An Activity being paused; ActivityRecord mLastPausedActivity: This is the most recently paused Activity; ActivityRecord mResumedActivity: the Activity that is currently in Resume state, that is, the Activity that is interacting with the user; ActivityRecord mLastNoHistoryActivity: This Activity is not added to the mTaskHistory list and will be destroyed once it leaves the screen; ActivityStackSupervisor mStackSupervisor: Specifies which ActivityStack is in the ActivityStackSupervisor.Copy the code
3.4 ActivityStackSupervisor
This class is used to manage multiple ActivityDisPlay objects and indirectly manage multiple ActivityStack objects through ActivityDisPlay objects. This class is initialized only by calling createStackSupervisor in AMS. And only the method is called in the AMS constructor for initialization, so only one instance object of the class exists in the AMS process.
ActivityStack mHomeStack: Store desktop-related activities; ActivityStack mFocusedStack: The ActivityStack that stores the current focus, i.e. the Activity that might be interacting with the user; ActivityStack mLastFocusedStack: If this variable is the same as the mFocusedStack variable object, the Activity at the top of the mFocusedStack has been successfully started and can interact with the user. If the mFocusedStack changes, the variable is the mFocusedStack before the change. If the new mFocusedStack is successfully started, the variable will be assigned to the new mFocusedStack. SparseArray<ActivityDisplay> mActivityDisplays: records ActivityDisplay;Copy the code
3.5 ActivityDisplay
Manage all activitystacks indirectly through ActivityDidplay in ActivityStackSupervisor. Each ActivityDisPlay corresponds to a display device, the default display device being the phone screen. The ActivityStackSupervisor indirectly maintains the state of multiple Activitystacks through ActivityDisplay. There is a member variable in ActivityDisPlay that manages all activitystacks:
<ActivityStack> mStacks = new ArrayList<>()Copy the code
3.6 ProcessRecord
Record all ActivityRecords that belong to a process. Activityrecords running in different TaskRecords may belong to the same ProcessRecord.
3.7 Correspondence
Store Activity data structure
4, summarize
The purpose of this introduction is to provide a general understanding of the launch mode, Flags in the Intent, and how activities are stored, to enhance the understanding of the source code. Of course, many of the above things are personal understanding, if there is a mistake in the place also hope to point out.