框架層理解Activity生命週期(APP啟動過程)

yangxi_001發表於2014-02-26

1生命週期圖


2主要類圖呼叫



上面類圖關係中包含兩個程式,一個是應用程式程式,另一個是AMS程式,所以會涉及到程式間通訊,android程式間通訊用的是Binder通訊。

2.1客戶程式

ØActivityThread

可以看到該類有一個main方法,其實它是android一個應用程式的入口,每啟動一個應用程式,都會建立ActivityThread與之對應的例項,是應用程式的UI執行緒,Android程式啟動時會建立訊息迴圈。負責管理應用程式的生命週期,執行系統廣播及其ActivityManagerService請求執行的操作。屬於客戶端物件。

ØApplicationThread&ApplicatinThreadNative

ApplicationThread用來實現ActivityManagerServiceActivityThread之間的互動。在ActivityManagerService需要管理相關Application中的Activity的生命週期時,通過ApplicationThreadActivityThread通訊,ApplicationThreadNativeApplicationThread在客戶端的實現。

ØApplicationThreadProxy

ApplicationThreadProxyApplicationThread在伺服器端的代理。負責和伺服器端的ApplicatingThreadNative通訊。

AMS就是通過該代理與ActivityThread進行通訊的。

ØActivity& Intrumentation

Activity是應用程式真正做事情的類,每一個應用程式只有一個Instrumentation物件,每個Activity內都有一個對該物件的引用。Instrumentation可以理解為應用程式的管家,ActivityThread要建立或暫停某個Activity時,都需要通過Instrumentation。通俗的理解,InstrumentationActivityThread的區別,前者像是一個“家庭”裡的“管家”,後者是負責建立這個“家庭”,並負責對外打交道,比如接收AMS的通知等。

2.2 AMS程式

這裡說的AMS程式,實際指的是System_server程式,System_server程式起來的時候啟動AMS服務,AMS實際是ActivityManagerService的縮寫。

ØActivityManagerService

管理Activity的生命週期

ØActivityManagerNative

ActivityManagerService在伺服器端的實現,客戶端的請求呼叫ActivityManagerProxy後,通過IBinder,最終會在ActivityManagerNative中實現。ActivityManagerNative再通過呼叫ActivityManagerService的相關功能,以完成客戶端請求。

ØActivityManagerProxy

ActivityManagerService的在客戶端的代理。負責和伺服器端的ActivityManagerNative通訊。

ØActivityStack

ActivityAMS的棧管理,用來記錄已經啟動的Activity的先後關係,狀態資訊等。通過ActivityStack決定是否需要啟動新的程式。

ØActivityRecord

ActivityStack的管理物件,每個ActivityAMS對應一個ActivityRecord來記錄Activity的狀態以及其他的管理資訊。

ØTaskRecord

AMS抽象出來的一個“任務”的概念,是記錄ActivityRecord的棧,一個“Task”包含若干個ActivityRecordAMSTaskRecord確保Activity啟動和退出的順序。

ØProcessRecord

一個Apk檔案執行時會對應一個程式,ProcessRecord正是記錄一個程式中的相關資訊。

3startActivity流程

Android系統中,應用程式是由Activity組成的,因此,應用程式的啟動過程實際上就是應用程式中的預設Activity的啟動過程。啟動Android應用程式中的Activity的兩種情景,第一,在android裝置螢幕中點選應用程式圖示的情景就會引發Android應用程式中的預設Activity的啟動,從而把應用程式啟動起來,這種啟動方式的特點是會啟動一個新的程式來載入相應的Activity。第二,應用程式內部啟動非預設Activity的過程的原始碼,這種非預設Activity一般是在原來的程式和任務中啟動的。在AndroidActivity管理機制中,當退出Activity的時候,在某些情況下並沒有立即把該Activity殺死,而是將其暫時儲存起來,當第二次呼叫startActivity啟動該Activity的時候,就不需要再建立該Activity的例項,直接恢復Activity即可。

3.1呼叫流程圖



對使用者來講,啟動一個Activity有以下幾種方式:

Ø在應用程式中呼叫startActivity()啟動指定的Activity

ØHome程式中點選一個應用圖示,啟動新的Activity

Ø按“Back”鍵,結束當前Activity,自動啟動上一個Activity

Ø長按“Home”鍵,顯示當前列表中,從中選則一個啟動

對於AMS內部講,啟動一個Activity有三種方式,如上圖中的①②③分支:

①目標Activity的物件已經存在,那麼直接resumeActivity

②目標Activity所在的程式不存在,那麼需要建立程式,並在新的程式中啟動該Activity

③目標Activity所在程式已經存在,那麼直接在已存在程式中啟動該Activity

3.2在新的程式中啟動

以在Home程式中點選一個應用圖示,啟動MainActivity為例子,介紹如下。

時序圖如下圖:

框架層理解Activity生命週期

以上時序圖包含35步驟呼叫,下面逐一講解:

3.2.1(1~4)Launcher中傳送startActivity請求

Android系統中,應用程式是由Launcher啟動起來的,其實,Launcher本身也是一個應用程式,其它的應用程式安裝後,就會Launcher的介面上出現一個相應的圖示,點選這個圖示時,Launcher就會對應的應用程式啟動起來。

Launcher繼承與ActivityActivity類的有個成員變數mInstrumentation是,它的型別是Intrumentation,它用來監控應用程式和系統的互動。


Instrumentation.execStartActivity

publicActivityResult execStartActivity(

Context who, IBinder contextThread, IBinder token, Activitytarget,

Intent intent, int requestCode, Bundle options) {

IApplicationThread whoThread = (IApplicationThread)contextThread;

……

try {

intent.setAllowFds(false);

intent.migrateExtraStreamToClipData();

int result = ActivityManagerNative.getDefault()

.startActivity(whoThread, intent,

intent.resolveTypeIfNeeded(who.getContentResolver()),

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

requestCode, 0, null, null, options);

checkStartActivityResult(result, intent);

} catch (RemoteException e) {

}

return null;

}

這裡的ActivityManagerNative.getDefault返回ActivityManagerService的遠端介面,即ActivityManagerProxy介面。

3.2.2(5-8)AMS接收客戶端startActivity請求

客戶端通過Binder呼叫,最終呼叫到ActivityStack.startActivityLocked

final intstartActivityLocked(IApplicationThread caller,

Intent intent, String resolvedType, ActivityInfo aInfo, IBinderresultTo,

String resultWho, int requestCode,

int callingPid, int callingUid, int startFlags, Bundleoptions,

boolean componentSpecified, ActivityRecord[] outActivity){

ProcessRecord callerApp = null;

if (caller != null) {

callerApp = mService.getRecordForAppLocked(caller);

if (callerApp != null) {

callingPid = callerApp.pid;

callingUid = callerApp.info.uid;

} else {

……

}

}

….

ActivityRecord sourceRecord = null;

ActivityRecord resultRecord = null;

….

int launchFlags = intent.getFlags();

….

if((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT)!= 0

&& sourceRecord != null){

// Transfer the result target from the source activity to thenew

// one being started, including any failures.

…….

}

……

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

intent, resolvedType, aInfo, mService.mConfiguration,

resultRecord, resultWho, requestCode,componentSpecified);

if (outActivity != null) {

outActivity[0] = r;

}

……

err = startActivityUncheckedLocked(r, sourceRecord,

startFlags, true, options);

……

return err;

}

startActivityLock()主要做了一下幾件事:

處理傳進來的引數caller,得到呼叫者的程式資訊,並儲存在callerApp變數中,這裡就是Launcher應用程式的程式資訊了。

處理FLAG_ACTIVITY_FORWARD_RESULT標誌。該標誌的特殊作用,就是能跨ActivityResult,比如A1->A2A2帶該標誌啟動A3,那麼A3呼叫setResult,然後finish(),結果將直接返回到A1

③建立一個臨時的ActivityRecord物件,該物件只為了後面呼叫過程中的各種對比,不一定會最終加入到mHistory列表中。

判斷mPendingActivityLaunches列表是否有等待的Activity要啟動,如果有先啟動等待的Activity

⑤呼叫startActivityUncheckedLocked()方法。此時要啟動的Activity已經通過檢驗,被人認為是一個正當的啟動請求。

3.2.3(9)建立新的Task

呼叫ActivityStack.startActivityUncheckedLocked()處理Task問題,因為這裡我們是新啟動一個apk,所以將建立新的TasknewTask=true,並呼叫ActivityStack.startActivityLoacked():

privatefinal void startActivityLocked(ActivityRecord r, booleannewTask,

boolean doResume, boolean keepCurTransition) {

……

if (!newTask) {

…….

}

}

// Place a new activity at top of stack, so it is next tointeract

// with the user.

if (addPos < 0) {

addPos = NH;

}

……

mHistory.add(addPos, r);

r.putInHistory();

r.frontOfTask = newTask;

……

if (doResume) {

resumeTopActivityLocked(null);

}

}

注意AtivityStack中有兩個startActivityLoacked()方法,這裡呼叫的是帶四個引數的,即startActivityLocked(ActivityRecord r, booleannewTask,boolean doResume, booleankeepCurTransition),其中,r為將要啟動的ActivitynewTask=truedoResume=true,在這個方法中,將r放到mHistory的最後面doResume=true,所以呼叫resumeTopActivityLocked(null)。關於Task的概念比較複雜,這裡先不講解。

3.2.4:(10)執行mHistory中最後一個ActivityRecord

ActivityStack. resumeTopActivityLocked(null)

finalboolean resumeTopActivityLocked(ActivityRecord prev) {

// Find the first activity that is not finishing.

ActivityRecord next = topRunningActivityLocked(null);

if (next == null) {

// There are no more activities!Let's just startup the

// Launcher...

if (mMainStack) {

return mService.startHomeActivityLocked();

}

}

next.delayedResume = false;

// If the top activity is the resumed one, nothing todo.

if (mResumedActivity == next &&next.state == ActivityState.RESUMED) {

// Make sure we have executed any pending transitions, sincethere

// should be nothing left to do at this point.

mService.mWindowManager.executeAppTransition();

mNoAnimActivities.clear();

return false;

}

// If we are sleeping, and there is no resumed activity, and thetop

// activity is paused, well that is the state we want.

if ((mService.mSleeping || mService.mShuttingDown)

&& mLastPausedActivity == next&& next.state ==ActivityState.PAUSED) {

// Make sure we have executed any pending transitions, sincethere

// should be nothing left to do at this point.

mService.mWindowManager.executeAppTransition();

mNoAnimActivities.clear();

returnfalse;

}

// The activity may be waiting for stop, but that is nolonger

// appropriate for it.

mStoppingActivities.remove(next);

mGoingToSleepActivities.remove(next);

next.sleeping = false;

mWaitingVisibleActivities.remove(next);

……

if (mPausingActivity != null) {

if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" +mPausingActivity);

return false;

}

…..

// We need to start pausing the current activity so the topone

// can be resumed...

if (mResumedActivity != null) {

if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to startpausing");

startPausingLocked(userLeaving, false);

return true;

}

……..

}

呼叫resumeTopActivityLocked(null)啟動真正的Activity

呼叫topRunningActivityLocked()方法取出當前正在執行的ActivityRecord物件

判斷mHistory中是否有記錄,如果沒有就意味著還沒有啟動任何的Activity,需要首先呼叫mService.startHomeActivityLocked()方法啟動所謂的“主介面程式”。當然我們這裡mHistroy已經有記錄了。

判斷正在執行的Activity是否和目標Activity一樣,如果一樣,則直接返回。

判斷當前系統是否處於休眠漲停,如果是,則返回。這裡繼續往下執行。

mStoppingActivitiesmWaitingVisibleActivitiesmGoingToSleepActivities中刪除目標物件,因為接下來將要被啟動。

判斷當前是否在暫停某個Activity,如果是則還不能執行。這裡mPausingActivity=null,所以繼續往下執行。

⑦判斷當前是否有Activity在執行,如果有則先需要暫停當前的Activity。因為我們是在Lancher中啟動mainActivity,所以當前mResumedActivity=null,所有呼叫startPausingLocked(userLeaving, false);

3.2.5(11~16)暫停當前執行Activity

①呼叫ActivityStack.startPausingLocked()暫停當前Activity

②判斷執行當前Activity的程式是否存在。在這裡 if (prev.app != null&& prev.app.thread !=null)為真。其中,prev.app為記錄啟動Lancher程式的ProcessRecordprev.app.threadLancher程式的遠端呼叫介面IApplicationThead,所以可以呼叫prev.app.thread.schedulePauseActivity,到Lancher程式暫停指定Activity

③在Lancher程式中訊息傳遞,呼叫ActivityThread.handlePauseActivity(),最終呼叫ActivityTHread.performPauseActivity暫停指定Activity。接著通過Binder通訊,通知AMS已經完成暫停ActivityManagerNative.getDefault().activityPaused(token).

3.2.6(17~20) AMS處理暫停Activity事情

Launcher通過Binder程式間通訊機制通知AMS,它已經準備就緒進入Paused狀態,在ActivityStack.completePauseLocked()中完成暫停:

private final void completePauseLocked(){

ActivityRecord prev = mPausingActivity;

if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);

if (prev != null) {

if (prev.finishing) {

prev = finishCurrentActivityLocked(prev,FINISH_AFTER_VISIBLE);

} else if (prev.app != null) {

……

if (prev.configDestroy) {

destroyActivityLocked(prev, true, false,"pause-config");

} else {

mStoppingActivities.add(prev);

if (mStoppingActivities.size() > 3) {

// If we already have a few activities waiting to stop,

// then give up on things going idle and start clearing

// them out.

if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcingidle");

scheduleIdleLocked();

} else {

checkReadyForSleepLocked();

}

}

} else {

if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping:" + prev);

prev = null;

}

mPausingActivity = null;

}

if (!mService.isSleeping()) {

resumeTopActivityLocked(prev);

} else {

checkReadyForSleepLocked();

}

……

}

①給prev賦值mPausingActivity,即上一個被執行的Activity,即Launcer

②如果prevfinishingtrue,說明上一個Activity已經完成,因此需要呼叫finishCurrentActivityLocked()執行相關操作。一般的流程不會為true,這個條件似乎只有記憶體回收的時候才會被執行。

③將mPausingActivity變數置為空

④呼叫resumeTopActivityLocked方法正式啟動目標Activity,即MainActivity

3.2.7(21~23)正式啟動目標Activity

呼叫AcivityStack.resumeTopActivityLocked

final booleanresumeTopActivityLocked(ActivityRecord prev) {

ActivityRecord next = topRunningActivityLocked(null);

……

if (mResumedActivity != null) {

if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to startpausing");

startPausingLocked(userLeaving, false);

return true;

}

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

……

}

startSpecificActivityLocked(next, true, true);

}

return true;

}

①該方法在3.2.4步驟中呼叫過,那時是因為mResumedActivity != null,有Activity正在執行,所以去執行了startPausingLocked暫停Laucher去了。這時候,mResumedActivity=null,所以繼續往下執行。

②判斷講要啟動的Activity的客戶程式是否存在,這裡next.app != null &&next.app.thread != nullfalse

③呼叫ActivityStack.startSpecificActivityLocked

private final voidstartSpecificActivityLocked(ActivityRecord r,

boolean andResume, boolean checkConfig) {

// Is this activity's application already running?

ProcessRecord app =mService.getProcessRecordLocked(r.processName,

r.info.applicationInfo.uid);

……

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

……

realStartActivityLocked(r, app, andResume, checkConfig);

return;

}

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

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

}

④客戶程式不存在,app!= null && app.thread !=nullfalse,所以呼叫mService.startProcessLocked() fork一個新的程式。

3.2.8(24) fork一個新的程式

AMS通過Socket通訊,向Zygote傳送一個建立程式請求,Zygote建立新程式。

②建立好程式後,呼叫ActivityThread.main()。到此,我們到了新了一個程式中,也是程式的入口出。

③呼叫ActivityThread.attach()開始新的應用程式,接著同過Binder通訊通知AMS,新的程式已經建立好了,可以開始新的程式了。

3.2.9(26~28) AMS準備執行目標Activity

目標程式啟動後,報告給AMS,自己已經啟動完畢可以啟動Activity了,這裡通過IPC呼叫AMSattachApplication方法完成。

ActivityManagerService.attachApplication():

public final voidattachApplication(IApplicationThread thread) {

synchronized (this) {

int callingPid = Binder.getCallingPid();

final long origId = Binder.clearCallingIdentity();

attachApplicationLocked(thread,callingPid);

Binder.restoreCallingIdentity(origId);

}

}

①根據Binder.getCallingPid(),或得客戶程式pid,並呼叫attachApplicationLocked(IApplicationThreadthread,int pid)

②在attachApplicationLocked中,根據pid找到對應的ProcessRecord物件,如果找不到說明改pid客戶程式是一個沒經過AMS允許的程式。

private final booleanattachApplicationLocked(IApplicationThread thread,

int pid) {

ProcessRecord app;

if (pid != MY_PID && pid>= 0) {

synchronized (mPidsSelfLocked) {

app = mPidsSelfLocked.get(pid);

}

}

if (app == null) {

……

returnfalse;

}

// If this application record is still attached to aprevious

// process, clean it up now.

if (app.thread != null) {

handleAppDiedLocked(app, true, true);

}

……

app.thread = thread;

app.curAdj = app.setAdj = -100;

app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;

app.setSchedGroup =Process.THREAD_GROUP_BG_NONINTERACTIVE;

app.forcingToForeground = null;

app.foregroundServices = false;

app.hasShownUi = false;

app.debugging = false;

……

ensurePackageDexOpt(app.instrumentationInfo != null

? app.instrumentationInfo.packageName

: app.info.packageName);

……

// See if the top visible activity is waiting to run in thisprocess...

ActivityRecord hr =mMainStack.topRunningActivityLocked(null);

if (hr != null && normalMode){

if (hr.app == null && app.info.uid== hr.info.applicationInfo.uid

&&processName.equals(hr.processName)) {

……

if (mMainStack.realStartActivityLocked(hr, app, true,true))

……

return true;

}

③為ProcessRecordapp物件內部變數賦值

④確保目標程式(APK)檔案已經被轉換為了odex檔案。Android中安裝程式是APK檔案,實際上是一個zip檔案。

⑤呼叫ActivityStack.realStartActivityLocked通知客戶程式執行指定Activity.

⑥呼叫ApplicationThread.scheduleLaunchActivity,啟動指定Activity

3.2.10:(29~35)客戶程式啟動指定Activity

AMS通過IPC通行,通知客戶程式啟動指定Activity

①呼叫ApplicationThread.scheduleLaunchActivity

②經過Handler訊息傳動,呼叫ActivityThread.handleLaunchActivity()

③呼叫ActivityThread.performLaunchActivity()完成Activity的載入,並最終呼叫Activity生命週期的onCreate()方法

performLaunchActivity返回,繼續呼叫ActivityThread.handleResumeActivity(),該方法內部又呼叫ActivityThread.performResumeActivity(),其內部僅僅呼叫了目標ActivityonResume()方法。到此Activity啟動完成。

⑤新增一個IdleHandler物件,因為在一般情況下,該步驟執行完畢後,Activity就會進入空閒狀態,所以就可以進行記憶體回收。

3.3在已有程式中啟動

在已有的程式中啟動Activity,也就是在一個應用程式中啟動內部Activity,其過程跟3.2小節大致一樣,這裡我們不會像3.2小節詳細分析每一步驟,我們只看差別的地方。這裡以啟動subActivity為例子。時序圖如下:





以上時序圖包含29步驟呼叫,下面逐一講解:

3.3.1(1~3)MainActivity啟動Activity

這一步跟3.2.1小節一樣

3.3.2(4~7) AMS接收客戶端startActivity請求

這一步跟3.2.2小節一樣

3.3.3(8)不需要建立新的Task

呼叫ActivityStack.startActivityUncheckedLocked()處理Task問題,因為這裡我們是在已有應用中startActivity,也不設定標誌要在新的Task中啟動Activity,所以不建立新的TasknewTask=false,並呼叫

ActivityStack.startActivityLoacked()

privatefinal void startActivityLocked(ActivityRecord r, booleannewTask,

boolean doResume, boolean keepCurTransition) {

……

if (!newTask) {

…….

}

}

// Place a new activity at top of stack, so it is next tointeract

// with the user.

if (addPos < 0) {

addPos = NH;

}

……

mHistory.add(addPos, r);

r.putInHistory();

r.frontOfTask = newTask;

……

if (doResume) {

resumeTopActivityLocked(null);

}

}

注意AtivityStack中有兩個startActivityLoacked()方法,這裡呼叫的是帶四個引數的,即startActivityLocked(ActivityRecord r, booleannewTask,boolean doResume, booleankeepCurTransition),其中,r為將要啟動的ActivitynewTask=falsedoResume=true,在這個方法中,將r放到mHistory的最後面doResume=true,所以呼叫resumeTopActivityLocked(null)

3.3.4(9)準備啟動mHistory中最後一個Activity

這一步跟3.2.4小節一樣

3.3.5(10~15)暫停MainActivity

這一步跟3.2.5小節一樣

3.3.6(16~19) AMS處理暫停MainActivity

這一步跟3.2.6小節一樣

3.3.7(20~22)正式啟動目標Activity

呼叫AcivityStack.resumeTopActivityLocked

final booleanresumeTopActivityLocked(ActivityRecord prev) {

ActivityRecord next = topRunningActivityLocked(null);

……

if (mResumedActivity != null) {

if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to startpausing");

startPausingLocked(userLeaving, false);

return true;

}

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

……

}

startSpecificActivityLocked(next, true, true);

}

return true;

}

①呼叫startSpecificActivityLocked(next, true,true)

private final voidstartSpecificActivityLocked(ActivityRecord r,

boolean andResume, boolean checkConfig) {

// Is this activity's application already running?

ProcessRecord app =mService.getProcessRecordLocked(r.processName,

r.info.applicationInfo.uid);

……

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

……

realStartActivityLocked(r, app, andResume, checkConfig);

return;

}

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

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

}

subActivity程式已經存在,app != null&& app.thread !=nulltrue,所以呼叫realStartActivityLocked

finalboolean realStartActivityLocked(ActivityRecord r,

ProcessRecord app, boolean andResume, booleancheckConfig)

throws RemoteException {

…..

app.thread.scheduleLaunchActivity(new Intent(r.intent),r.appToken,

System.identityHashCode(r), r.info,

new Configuration(mService.mConfiguration),

r.compat, r.icicle, results, newIntents,!andResume,

mService.isNextTransitionForward(), profileFile,profileFd,

profileAutoStop);

……

return true;

}

③呼叫ApplicationThread.scheduleLaunchActivity,啟動指定Activity

3.3.8(23~29)客戶程式啟動指定Activity

這一步跟3.2.10是一樣的

3.4在已有的ActivityRecord中恢復指定Activity

經過上面3.23.3小節,現在對Activity的啟動流程應該是比較清晰的了,這一節就簡單的講下恢復Activity的流程。當ActivityRecord已經記錄有一個Activity,如果再次呼叫startActivity,並沒有標誌要建立Activity新的例項,那麼就可以直接恢復該Activity

啟動一個Activity,跟前面3.2節一樣,都需要暫停當前正在執行的Activity,暫停流程這裡就不講了,完成暫停後,呼叫ActivityStack.resumeTopActivityLocked()

因為AMSActivityTHreadIPC通訊,resumeTopActivityLocked會被反覆呼叫幾次,每次都會根據一些變數值的差異,走不同的流程。

finalboolean resumeTopActivityLocked(ActivityRecord prev) {

// Find the first activity that is not finishing.

ActivityRecord next = topRunningActivityLocked(null);

……

if (mResumedActivity != null) {

if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to startpausing");

startPausingLocked(userLeaving, false);

return true;

}

……

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

if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " +next);

……

try {

……

next.app.thread.scheduleResumeActivity(next.appToken,

mService.isNextTransitionForward());

checkReadyForSleepLocked();

} catch (Exception e) {

// Whoops, need to restart this activity!

……

startSpecificActivityLocked(next, true, false);

return true;

}

……

} else {

……

return true;

}

③這裡,mResumedActivity = null,不走暫停流程。

next.app != null &&next.app.thread != nulltrue,呼叫ApplicationThead.scheduleResumeActivity(),到客戶程式恢復指定Activity

經過訊息傳遞,呼叫ActivityTHread.handleResumeActivity()

呼叫ActivityTHread.performResumeActivity()正在恢復Activity,接著回撥ActivityonResume()方法。

4 stop停止Activity

前面幾節彙總,A啟動到B時,需要先暫停A,然後再啟動B。什麼時候停止(stop)或者銷燬(Destory)呢?

4.1從暫停到停止全過程



4Home鍵回到桌面

5Back鍵回到上一個Activity

6長按Home

轉自:http://blog.csdn.net/fe421504975/article/details/8272128

相關文章