ActivityRecord、TaskRecord、ActivityStack以及Activity啓動模式詳解

1.簡介

先來張簡單的關係圖:java

在這裏插入圖片描述

ActivityStack、TaskRecord、ActivityRecord關係圖android

  • 一個ActivityRecord對應一個Activity,保存了一個Activity的全部信息;可是一個Activity可能會有多個ActivityRecord,由於Activity能夠被屢次啓動,這個主要取決於其啓動模式。
  • 一個TaskRecord由一個或者多個ActivityRecord組成,這就是咱們常說的任務棧,具備後進先出的特色。
  • ActivityStack則是用來管理TaskRecord的,包含了多個TaskRecord。

下面進入詳細的代碼分析,本文源碼基於android 27。shell

2.代碼分析

2.1 ActivityRecord

ActivityRecord,源碼中的註釋介紹:An entry in the history stack, representing an activity.
翻譯:歷史棧中的一個條目,表明一個activity。app

frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java
    
    final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {

        final ActivityManagerService service; // owner
        final IApplicationToken.Stub appToken; // window manager token
        AppWindowContainerController mWindowContainerController;
        final ActivityInfo info; // all about me
        final ApplicationInfo appInfo; // information about activity's app
        
        //省略其餘成員變量
        
        //ActivityRecord所在的TaskRecord
        private TaskRecord task;        // the task this is in.
        
        //構造方法,須要傳遞大量信息
        ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid,
                       int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
                       ActivityInfo aInfo, Configuration _configuration,
                       com.android.server.am.ActivityRecord _resultTo, String _resultWho, int _reqCode,
                       boolean _componentSpecified, boolean _rootVoiceInteraction,
                       ActivityStackSupervisor supervisor, ActivityOptions options,
                       com.android.server.am.ActivityRecord sourceRecord) {
        
        }
    }
  • 實際上,ActivityRecord中存在着大量的成員變量,包含了一個Activity的全部信息。
  • ActivityRecord中的成員變量task表示其所在的TaskRecord,由此能夠看出:ActivityRecord與TaskRecord創建了聯繫。

startActivity()時會建立一個ActivityRecord:this

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

    class ActivityStarter {
        private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
                                  String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
                                  IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                                  IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
                                  String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
                                  ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
                                  com.android.server.am.ActivityRecord[] outActivity, TaskRecord inTask) {

            //其餘代碼略
            
            ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                    callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                    resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                    mSupervisor, options, sourceRecord);
                    
            //其餘代碼略
        }
    }

2.2 TaskRecord

TaskRecord,內部維護一個ArrayList<ActivityRecord>用來保存ActivityRecord。google

frameworks/base/services/core/java/com/android/server/am/TaskRecord.java
    
    final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
        final int taskId;       //任務ID
        final ArrayList<ActivityRecord> mActivities;   //使用一個ArrayList來保存全部的ActivityRecord
        private ActivityStack mStack;   //TaskRecord所在的ActivityStack
        
        //構造方法
        TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
                   IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, int type) {
            
        }
        
        //添加Activity到頂部
        void addActivityToTop(com.android.server.am.ActivityRecord r) {
            addActivityAtIndex(mActivities.size(), r);
        }
        
        //添加Activity到指定的索引位置
        void addActivityAtIndex(int index, ActivityRecord r) {
            //...

            r.setTask(this);//爲ActivityRecord設置TaskRecord,就是這裏創建的聯繫

            //...
            
            index = Math.min(size, index);
            mActivities.add(index, r);//添加到mActivities
            
            //...
        }

        //其餘代碼略
    }
  • 能夠看到TaskRecord中使用了一個ArrayList來保存全部的ActivityRecord。
  • 一樣,TaskRecord中的mStack表示其所在的ActivityStack。

startActivity()時也會建立一個TaskRecord:spa

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
    
    class ActivityStarter {

        private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
            mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);

            if (mReuseTask == null) {
                //建立一個createTaskRecord,其實是調用ActivityStack裏面的createTaskRecord()方法,ActivityStack下面會講到
                final TaskRecord task = mTargetStack.createTaskRecord(
                        mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                        mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                        mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
                        mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);

                //其餘代碼略
            }
        }
    }

2.3 ActivityStack

ActivityStack,內部維護了一個ArrayList<TaskRecord>,用來管理TaskRecord。翻譯

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
    
    class ActivityStack<T extends StackWindowController> extends ConfigurationContainer implements StackWindowListener {

        private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();//使用一個ArrayList來保存TaskRecord

        final int mStackId;

        protected final ActivityStackSupervisor mStackSupervisor;//持有一個ActivityStackSupervisor,全部的運行中的ActivityStacks都經過它來進行管理
        
        //構造方法
        ActivityStack(ActivityStackSupervisor.ActivityDisplay display, int stackId,
                      ActivityStackSupervisor supervisor, RecentTasks recentTasks, boolean onTop) {

        }
        
        TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
                                    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                                    boolean toTop, int type) {
                                    
            //建立一個task
            TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession, voiceInteractor, type);
            
            //將task添加到ActivityStack中去
            addTask(task, toTop, "createTaskRecord");

            //其餘代碼略

            return task;
        }
        
        //添加Task
        void addTask(final TaskRecord task, final boolean toTop, String reason) {

            addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);

            //其餘代碼略
        }

        //添加Task到指定位置
        void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
                     String reason) {
            mTaskHistory.remove(task);//若存在,先移除
            
            //...
            
            mTaskHistory.add(position, task);//添加task到mTaskHistory
            task.setStack(this);//爲TaskRecord設置ActivityStack

            //...
        }
        
        //其餘代碼略
    }
  • 能夠看到ActivityStack使用了一個ArrayList來保存TaskRecord。
  • 另外,ActivityStack中還持有ActivityStackSupervisor對象,這個是用來管理ActivityStacks的。

ActivityStack是由ActivityStackSupervisor來建立的,實際ActivityStackSupervisor就是用來管理ActivityStack的,繼續看下面的ActivityStackSupervisor分析。3d

2.4 ActivityStackSupervisor

ActivityStackSupervisor,顧名思義,就是用來管理ActivityStack的。code

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
    
    public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {

        ActivityStack mHomeStack;//管理的是Launcher相關的任務

        ActivityStack mFocusedStack;//管理非Launcher相關的任務
        
        //建立ActivityStack
        ActivityStack createStack(int stackId, ActivityStackSupervisor.ActivityDisplay display, boolean onTop) {
            switch (stackId) {
                case PINNED_STACK_ID:
                    //PinnedActivityStack是ActivityStack的子類
                    return new PinnedActivityStack(display, stackId, this, mRecentTasks, onTop);
                default:
                    //建立一個ActivityStack
                    return new ActivityStack(display, stackId, this, mRecentTasks, onTop);
            }
        }

    }
  • ActivityStackSupervisor內部有兩個不一樣的ActivityStack對象:mHomeStack、mFocusedStack,用來管理不一樣的任務。
  • ActivityStackSupervisor內部包含了建立ActivityStack對象的方法。

AMS初始化時會建立一個ActivityStackSupervisor對象。

2.5 總結

因此,實際上,他們的關係應該是這樣的:

ActivityStack、TaskRecord、ActivityRecord、ActivityStackSupervisor關係圖

3. 場景分析

下面經過啓動Activity的代碼來分析一下:

3.1 桌面

首先,咱們看下處於桌面時的狀態,運行命令:

adb shell dumpsys activity

結果以下:

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
  Stack #0:
  
  //中間省略其餘...
  
    Task id #102
    
  //中間省略其餘...
  
      TaskRecord{446ae9e #102 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.google.android.apps.nexuslauncher/.NexusLauncherActivity }
        Hist #0: ActivityRecord{54fa22 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t102}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.google.android.apps.nexuslauncher/.NexusLauncherActivity }
          ProcessRecord{19c7c43 2203:com.google.android.apps.nexuslauncher/u0a22}

    Running activities (most recent first):
      TaskRecord{446ae9e #102 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{54fa22 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t102}

    mResumedActivity: ActivityRecord{54fa22 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t102}
    
//省略其餘

實際上就是以下圖所示的結構,這裏的Stack #0就是ActivityStackSupervisor中的mHomeStack,mHomeStack管理的是Launcher相關的任務。

桌面下的狀態

3.2 從桌面啓動一個Activity

從桌面啓動一個APP,而後運行上面的命令,爲了節省篇幅,這裏和後面就不貼結果了,直接放圖了。

從桌面點擊圖標啓動一個AActivity,能夠看到,會多了一個Stack #1,這個Stack #1就是ActivityStackSupervisor中的mFocusedStack,mFocusedStack負責管理的是非Launcher相關的任務。同時也會建立一個新的ActivityRecord和TaskRecord,ActivityRecord放到TaskRecord中,TaskRecord則放進mFocusedStack中。

啓動A

3.3 默認模式從A啓動B

而後,咱們從AActivity中啓動一個BActivity,能夠看到會建立一個新的ActivityRecord而後放到已有的TaskRecord棧頂。

默認(standerd)模式啓動B

3.4 從A啓動B建立新棧

若是咱們想啓動的BActivity在一個新的棧中呢,咱們能夠用singleInstance的方式來啓動BActivity。singleInstance後面也會講到。這種方式會建立一個新的ActivityRecord和TaskRecord,把ActivityRecord放到新的TaskRecord中去。

啓動新Task

4. 流程分析

4.1 啓動流程

這裏對啓動Activity過程當中涉及到的ActivityStack、TaskRecord、ActivityRecord、ActivityStackSupervisor進行簡單的分析,實際上一張時序圖就能夠看明白了。相關的代碼能夠看上面的內容。

Activity啓動UML類圖

簡單總結:
1.startActivity時首先會建立一個ActivityRecord。
2.若是有須要,會建立一個TaskRecord,並把這個TaskRecord加入到ActivityStack中。
3.將ActivityRecord添加到TaskRecord的棧頂。

5. 啓動模式

相信看完上面的介紹,如今再來看啓動模式那是so easy了。

5.1 standerd

默認模式,每次啓動Activity都會建立一個新的Activity實例。

好比:如今有個A Activity,咱們在A上面啓動B,再而後在B上面啓動A,其過程如圖所示:


standerd

5.2 singleTop

若是要啓動的Activity已經在棧頂,則不會從新建立Activity,只會調用該該Activity的onNewIntent()方法。
若是要啓動的Activity不在棧頂,則會從新建立該Activity的實例。

好比:如今有個A Activity,咱們在A以standerd模式上面啓動B,而後在B上面以singleTop模式啓動A,其過程如圖所示,這裏會新建立一個A實例:

singleTop_A

若是在B上面以singleTop模式啓動B的話,則不會從新建立B,只會調用onNewIntent()方法,其過程如圖所示:

singleTop_B.png

5.3 singleTask

若是要啓動的Activity已經存在於它想要歸屬的棧中,那麼不會建立該Activity實例,將棧中位於該Activity上的全部的Activity出棧,同時該Activity的onNewIntent()方法會被調用。
若是要啓動的Activity不存在於它想要歸屬的棧中,而且該棧存在,則會建立該Activity的實例。
若是要啓動的Activity想要歸屬的棧不存在,則首先要建立一個新棧,而後建立該Activity實例並壓入到新棧中。

好比:如今有個A Activity,咱們在A以standerd模式上面啓動B,而後在B上面以singleTask模式啓動A,其過程如圖所示:

singleTask

5.4 singleInstance

基本和singleTask同樣,不一樣的是啓動Activity時,首先要建立在一個新棧,而後建立該Activity實例並壓入新棧中,新棧中只會存在這一個Activity實例。

好比:如今有個A Activity,咱們在A以singleInstance模式上面啓動B,其過程如圖所示:

singleInstance

6.Intent的FLAG

另外,若是startActivity()時往Intent 中加入相應的標誌來指定啓動模式,這種方式的優先級會比在AndroidManifest中定義的優先級高;可是AndroidManifest中只能定義四種啓動方式:standard、singleTop、singleTask、singleInstance,而Intent的flag則有不少種。具體的能夠看看文檔,咱們這裏看看部分flag:

  • FLAG_ACTIVITY_NEW_TASK :跟launchMode中的singleTask同樣。
  • FLAG_ACTIVITY_SINGLE_TOP :跟launchMode中的singleTop同樣。
  • FLAG_ACTIVITY_CLEAR_TOP :launchMode中沒有對應的值,若是要啓動的Activity已經存在於棧中,則將全部位於它上面的Activity出棧。singleTask默認具備此標記位的效果。
相關文章
相關標籤/搜索