自由筆記-Activity之啓動流程分析

Activity框架和管理結構

Activity管理的核心是AcitivityManagerService,是一個獨立的進程;

ActiveThread是每一個應用程序所在進程的主線程,循環的消息處理;

ActiveThread與AcitivityManagerService的通信是屬於進程間通信,使用binder機制,通過ApplicationThread這個橋樑進行通信

ApplicationThread是ActivityThread的一個內部類

一個應用程序中所有Activity只有一個ActivityThread屬於一個Process

 

ActiveThread重要成員介紹:

final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();//activity記錄類

final ApplicationThread mAppThread = new ApplicationThread();用來與AMS交互通信的橋樑,是一個binder.

final H mH = new H();消息循環handler。

Instrumentation mInstrumentation;用於監控程序和系統之間的交互操作

 

 

ActivityManagerService:Activity管理服務類,通過mHistory棧來管理所有的activity,應用啓動activity之後,發動啓動請求到AMS,AMS會根據

activity、ProcessRecord等信息創建HistoryRecord實例r並加入到mHistory當中。activity被加入到mHistory之後,只是說明在服務端可以找到該

activity記錄了,但是在客戶端目前還沒有該activity記錄。還需要通過ProcessRecord中的thread(IApplication)變量,調用它的

scheduleLaunchActivity方法在ActivityThread中創建新的ActivityRecord記錄(之前我們說過,客戶端的activity是用ActivityRecord

記錄的,並放在mActivities中)

app.thread.scheduleLaunchActivity(new Intent(r.intent), r,System.identityHashCode(r),

 

ActivityRecord:activity記錄類,代表一個Activity。

 

TaskRecord:任務棧記錄類,代表一個存放activity的任務棧

 

ActivityStarter:activity啓動前邏輯處理類,主要收集所有的邏輯來確定意圖(intent)和標誌(flag),然後轉變爲對應的活動(activity)和關聯的任務和堆棧

 

ActivityStack:activtiy任務棧管理類,維護着一個private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();負責管理各個activity的任務棧

 

ActivityStackSupervisor:任務棧超級管理員,其實算ActivityStack的輔助管理類,它和ActivityStack相互持有

 

系統啓動的時候,會創建一個PackageManagerService,PackageManagerService會對應用程序的配置文件AndroidManifest.xml進行解析,從而得到程序裏的組件信息。

PackageManagerService去查詢所有action爲“android.intent.action.MAIN”並且category爲“android.intent.category.LAUNCHER”的Activity,然後爲每個

應用程序創建一個快捷方式圖標,並把程序信息與之關聯,作爲啓動的第一個Activity。

 

我將activty啓動分爲以下幾步:

1、客戶端發出啓動activity命令;

2、AMS接受到命令,啓動Activity相關工作

3、AMS查詢當前需要啓動activity的任務棧是否有需要執行onPasue的activity,如果有執行,如果沒有啓動activity

4、如果有需要執行onPause的activity,那麼回調客戶端調用該方法

5、該方法調用完成後,通知AMS啓動需要啓動的activity

6、需要啓動的activity準備信息完成後,判斷該activity所屬進程是否已經啓動,如果啓動,直接啓動activity,如果沒有,先啓動進程,進入到該進程的activityThread的main方法

7、AMS啓動activity,通知客戶端,調用app.thread.scheduleLaunchActivity

8、客戶端執行scheduleLaunchActivity,進行activity的一系列啓動動作:生命週期方法執行、設置視圖、通知WMS繪製視圖

9、activity成功啓動後,通知AMS讓需要執行onStop方法的activity執行該方法

 

其中1-7步主要在AMS部分執行

第8步在客戶端執行

第9步在AMS執行

 

AMS部分:

 

1、不管是從lancher啓動還是應用內啓動,最原始的起點,都是activity內部的startActivity方法

 

@Override

public void startActivity(Intent intent, @Nullable Bundle options) {

if (options != null) {

startActivityForResult(intent, -1, options);

} else {

startActivityForResult(intent, -1);

}

}

參數requestCode=-1表示不需要把結果傳送回來。

 

然後進入到Instrumentation的execStartActivity方法,然後會調用

int result = ActivityManagerNative.getDefault()

.startActivity(whoThread, who.getBasePackageName(), intent,

intent.resolveTypeIfNeeded(who.getContentResolver()),

token, target != null ? target.mEmbeddedID : null,

requestCode, 0, null, options);

進入到AMS中的startActivity方法中

 

2、AMS中的startActivity的方法線

startActivity->startActivityAsUser->mActivityStarter.startActivityMayWait

 

3、進入到ActivityStarter,對Intent進行分析處理

startActivityMayWait->startActivityLocked->startActivityUnchecked->ActivityStack.startActivityLocked->ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

 

在Starter的startActivityLocked方法中,有一個非常重要的地方,就是創建了一個ActivityRecord,表示一個Activity的所有信息

ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,

intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,

requestCode, componentSpecified, voiceSession != null, mSupervisor, container,

options, sourceRecord);

在這個ActivityRecoder中,我們有一點要記住,它創建了一個 appToken = new Token(this, service);

它是一個static class Token extends IApplicationToken.Stub,代表着這個Activity,這個Token最終是和WMS交互的身份校驗符

 

接下來進入startActivityUnchecked方法,這裏主要做一些啓動前的任務棧、Activity狀態的初始化工作,

然後進入到ActivityStack.startActivityLocked將token傳遞給WMS

最後進入到ActivityStackSupervisor.resumeFocusedStackTopActivityLocked方法

 

4、進入到ActivityStack的startActivityLocked方法,將剛剛生成的token傳遞給WMS

startActivityLocked->addConfigOverride->mWindowManager.addAppToken(......);

 

5、進入到ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

resumeFocusedStackTopActivityLocked->ActivityStack.resumeTopActivityUncheckedLocked->ActivityStack.resumeTopActivityInnerLocked

 

resumeTopActivityInnerLocked這個方法是啓動前的最終檢查,這裏會有一個判斷:

if (mResumedActivity != null) {

if (DEBUG_STATES) Slog.d(TAG_STATES,

"resumeTopActivityLocked: Pausing " + mResumedActivity);

pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);

}

if (pausing) {

if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,

"resumeTopActivityLocked: Skip resume: need to start pausing");

// At this point we want to put the upcoming activity's process

// at the top of the LRU list, since we know we will be needing it

// very soon and it would be a waste to let it get killed if it

// happens to be sitting towards the end.

if (next.app != null && next.app.thread != null) {

mService.updateLruProcessLocked(next.app, true, null);

}

if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();

return true;

}

如果任務棧頂的Activity不爲null,那麼執行上一個activity的onPasuse方法,然後返回,該方法到此爲止

如果沒有執行onPause方法的activity,又會進行下一個判斷:

if (next.app != null && next.app.thread != null) {

......

}else{

mStackSupervisor.startSpecificActivityLocked(next, true, true);

}

這裏很好理解,如果要啓動的activity已經創建過了,那麼再次把它放到棧頂,會執行onRestart方法然後走對應的生命週期

如果沒有那麼進入到mStackSupervisor.startSpecificActivityLocked方法來創建一個新的activity。這裏我們先不分析,我們先分析onPause這條線,最後也會走到mStackSupervisor.startSpecificActivityLocked這裏來的

 

6、進入到ActivityStack.startPausingLocked方法

首先會執行completePauseLocked

在ActivityStack.completePauseLocked的方法中,有一個判斷當上一個activity不可見了,是pause狀態,那麼執行addToStopping方法

if (!mStackSupervisor.mStoppingActivities.contains(r)) {

mStackSupervisor.mStoppingActivities.add(r);

}

將該activity加入到mStoppingActivities集合中,等待調用onStop方法

if (prev.app != null && prev.app.thread != null) {

if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);

try {

EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,

prev.userId, System.identityHashCode(prev),

prev.shortComponentName);

mService.updateUsageStats(prev, false);

prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,

userLeaving, prev.configChangeFlags, dontWait);

} catch (Exception e) {

// Ignore exception, if process died other code will cleanup.

Slog.w(TAG, "Exception thrown during pause", e);

mPausingActivity = null;

mLastPausedActivity = null;

mLastNoHistoryActivity = null;

}

}

這裏可以看出,如果棧頂activity確實存在,並且進程沒有死掉,那麼會回調它的schedulePauseActivity方法,至此,我們回到客戶端的ActivityThread.ApplicationThread中

 

7、ApplicationThread.schedulePauseActivity方法

發送了一個PAUSE_ACTIVITY的message,然後進入到handlePauseActivity方法

handlePauseActivity->performPauseActivity->performPauseActivityIfNeeded->mInstrumentation.callActivityOnPause(r.activity)->activity.performPause();

至此,上一個activity的onPause方法執行

if (!dontReport) {

try {

ActivityManagerNative.getDefault().activityPaused(token);

} catch (RemoteException ex) {

throw ex.rethrowFromSystemServer();

}

}

至此,我們又回到了AMS中的activityPaused方法

 

8、AMS的activityPaused方法

activityPaused->ActivityStack.activityPausedLocked->ActivityStack.completePauseLocked

然後又調用了mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);

我們又進入到了ActivityStackSupervisor.resumeFocusedStackTopActivityLocked的方法,

 

9、又進入到ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

resumeFocusedStackTopActivityLocked->ActivityStack.resumeTopActivityUncheckedLocked->ActivityStack.resumeTopActivityInnerLocked

再次進入該方法後,之前的pause方法那裏會跳過,會根據獲取到的棧頂activity next的狀態來判斷:

如果沒有執行onPause方法的activity,又會進行下一個判斷:

if (next.app != null && next.app.thread != null) {

......

}else{

mStackSupervisor.startSpecificActivityLocked(next, true, true);

}

這裏很好理解,如果要啓動的activity已經創建過了,那麼再次把它放到棧頂,會執行onRestart方法然後走對應的生命週期

如果沒有那麼進入到mStackSupervisor.startSpecificActivityLocked方法來創建一個新的activity。

所以,接下來進入到mStackSupervisor.startSpecificActivityLocked方法

 

10、進入到startSpecificActivityLocked方法

ProcessRecord app = mService.getProcessRecordLocked(r.processName,

r.info.applicationInfo.uid, true);

首先獲取到該activity所屬的進程,判斷該activity的進程是否已經啓動,如果已經啓動進入startSpecificActivityLocked方法回調客戶端的app.thread.scheduleLaunchActivity方法

如果該activity的進程沒有啓動,那麼啓動進程

mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,

"activity", r.intent.getComponent(), false, false, true);

我們這裏重點分析啓動進程的這一塊,因爲這一塊最後也會進入到app.thread.scheduleLaunchActivity方法

 

11、啓動進程後,會執行客戶端的ActivityThread的main方法。

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();

thread.attach(false);

if (sMainThreadHandler == null) {

sMainThreadHandler = thread.getHandler();

}

Looper.loop();

在Main方法中,開啓UI線程消息隊列循環,新建ActivityThread對象,執行ActivityThread的attach方法

attach函數主要通過binder機制與AMS進行通信,它主要做了:

將ApplicationThread與ActivityManager進行綁定

final IActivityManager mgr = ActivityManagerNative.getDefault();

try {

mgr.attachApplication(mAppThread);

} catch (RemoteException ex) {

throw ex.rethrowFromSystemServer();

}

通過調用AMS的代理attachApplication方法來實現。這樣在AMS中建立了app進程ProcessRecord的信息,通過這個ProcessRecord就可以回調

ApplicationThread中的方法來啓動app進程中的activity。

 

11、在AMS中,先調用了attachApplication方法,

attachApplication->attachApplicationLocked->mStackSupervisor.attachApplicationLocked

在attachApplicationLocked方法中,進行了application的綁定:thread.bindApplication(......)

handleBindApplication方法裏面做了兩件事:

1、創建Instrumentation

2、在LoadedApk中創建Application app = data.info.makeApplication(data.restrictedBackupMode, null);在ActivityThread中賦值給mInitialApplication;

我們來看makeApplication方法:

ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);

app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);

創建ContextImpl並賦值給Application,這個ContextImpl就是Application的mBase變量,也就是getBaseContext所獲取的值,在Context專題中會講到,在Activity也會遇到它

不管是Activity還是Application中去調用getApplicationContext,最後都會調用

@Override

public Context getApplicationContext() {

return (mPackageInfo != null) ?

mPackageInfo.getApplication() : mMainThread.getApplication();

}

mPackageInfo.getApplication()或者mMainThread.getApplication()都指向剛剛創建的application

 

然後調用了mStackSupervisor.attachApplicationLocked(app)方法。在該方法中會調用realStartActivityLocked(hr, app, true, true)方法。

在該方法中又會調用app.thread.scheduleLaunchActivity方法回到activityThread中啓動activity。

 

 

客戶端部分:

 

12、scheduleLaunchActivity->handleLaunchActivity->performLaunchActivity->handleResumeActivity

在scheduleLaunchActivity方法裏面會創建一個ActivityClientRecord r = new ActivityClientRecord();對象它對應着AMS的ActivityRecord

在與AMS綁定了之後,AMS會最終會調用ApplicationThread的scheduleLaunchActivity方法,該方法會用H發送一個 sendMessage(H.LAUNCH_ACTIVITY, r);消息

在H中,接受到消息之後,會調用 handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");方法

 

首先調用performLaunchActivity生成Activity實例,並對其參數進行初始化,這裏包括

1、創建activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);

2、如果application沒有創建或者啓動,創建

3、創建ContextImpl Context appContext = createBaseContextForActivity(r, activity);

4、執行activity.attach方法,設定mBase爲剛剛創建的ContextImpl,創建mWindow = new PhoneWindow(this, window);設定window的回調爲自身,設定window的windowManager

5、執行聲明週期函數onCreate,mInstrumentation.callActivityOnCreate,執行onStart方法activity.performStart();

最後將activity存放到集合中,mActivities.put(r.token, r);

 

接下來進入handleResumeActivity方法

首先執行performResumeActivity方法,執行activity的onResume方法 r.activity.performResume();

 

執行完相關生命週期函數之後,handleResumeActivity方法裏開始進行窗口綁定,將activity顯示到窗口上。

r.window = r.activity.getWindow();

View decor = r.window.getDecorView();

decor.setVisibility(View.INVISIBLE);

ViewManager wm = a.getWindowManager();

WindowManager.LayoutParams l = r.window.getAttributes();

a.mDecor = decor;

l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;

l.softInputMode |= forwardBit;

if (r.mPreserveWindow) {

a.mWindowAdded = true;

r.mPreserveWindow = false;

// Normally the ViewRoot sets up callbacks with the Activity

// in addView->ViewRootImpl#setView. If we are instead reusing

// the decor view we have to notify the view root that the

// callbacks may have changed.

ViewRootImpl impl = decor.getViewRootImpl();

if (impl != null) {

impl.notifyChildRebuilt();

}

}

if (a.mVisibleFromClient && !a.mWindowAdded) {

a.mWindowAdded = true;

wm.addView(decor, l);

}

 

 

13、當activity成功啓動,並且執行完生命週期函數後,繼續通知AMS執行之前activity的onStop方法

Looper.myQueue().addIdleHandler(new Idler());

在最後會往消息隊列裏面傳遞一個閒時任務,這個任務會調用AMS的方法

am.activityIdle(a.token, a.createdConfig, stopProfiling);

activityIdle->mStackSupervisor.activityIdleInternalLocked->stack.stopActivityLocked

ActivityRecord r =mStackSupervisor.activityIdleInternalLocked(token, false, config);

for (int i = 0; i < NS; i++) {

r = stops.get(i);

final ActivityStack stack = r.task.stack;

if (stack != null) {

if (r.finishing) {

stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);

} else {

stack.stopActivityLocked(r);

}

}

}

如果是銷燬掉的activity,執行finishCurrentActivityLocked,如果只是執行onStop方法,執行stopActivityLocked

在stopActivityLocked方法裏面我們可以看到r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);

最終就執行了onStop方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章