Activity啟動過程分析
通常我們在Activity中啟動一個另一個Activity某残,就是調(diào)用Activity的startActivity方法,這個最終會調(diào)用到Activity的startActivityForResult方法荸百。那你有沒有想過Activity的啟動到底經(jīng)歷了哪些過程,我們今天就來分析一下鼠冕。
在具體分析之前,要先說明一下,Activity的啟動流程在細(xì)節(jié)挺繁瑣的,比如啟動另一個App的Activity或者啟動不同的launchMode的Activity刑顺,在細(xì)節(jié)上都會有不同。我們這次的源碼分析著重分析一下流程饲常,為了簡單起見蹲堂,就以分析一個Activity啟動app內(nèi)部另一個standard模式的Activity為主。
Activity啟動另一個Activity之前贝淤,當(dāng)前的Activity先要執(zhí)行onPause柒竞,被啟動的Activity才會執(zhí)行到onResume方法。這中間實(shí)際上是會執(zhí)行4次IPC過程的:
當(dāng)前Activity發(fā)起啟動另一個Activity的請求——>ActivityManagerService
ActivityManagerService——> 通知App暫停當(dāng)前Activity
當(dāng)前App告知已經(jīng)暫停了當(dāng)前的Activity——> ActivityManagerService
ActivityManagerService ——> 通知App啟動新的Activity
注:本次源碼分析采用Android7.0播聪,不同版本的源碼在細(xì)節(jié)上會有不同朽基,比如,在Android8.0上ActivityManagerService就改成了以AIDL的方式來寫离陶,請不要太糾結(jié)API的不同稼虎。
注:本文Activity啟動過程源碼分析過程比較長,代碼較繁瑣招刨,請做好心理準(zhǔn)備霎俩。
Activity啟動涉及到的類
首先要簡單介紹一下Activity啟動過程涉及到的類,以便于更好的理解這個啟動過程沉眶。
ActivityThread:App啟動的入口
ApplicationThread:ActivityThread的內(nèi)部類打却,繼承Binder,可以進(jìn)程跨進(jìn)程通信沦寂。
ApplicationThreadProxy:ApplicationThread的一個本地代理学密,其它的client端通過這個對象調(diào)用server端ApplicationThread中方法。
Instrumentation:負(fù)責(zé)發(fā)起Activity的啟動传藏、并具體負(fù)責(zé)Activity的創(chuàng)建以及Activity生命周期的回調(diào)腻暮。一個應(yīng)用進(jìn)程只會有一個Instrumentation對象,App內(nèi)的所有Activity都持有該對象的引用毯侦。
ActivityManagerService:簡稱AMS哭靖,是service端對象,負(fù)責(zé)管理系統(tǒng)中所有的Activity
ActivityManagerProxy:是ActivityManagerService的本地代理
ActivityStack:Activity在AMS的棧管理侈离,用來記錄已經(jīng)啟動的Activity的先后關(guān)系试幽,狀態(tài)信息等。通過ActivityStack決定是否需要啟動新的進(jìn)程卦碾。
ActivityRecord:ActivityStack的管理對象铺坞,每個Activity在AMS對應(yīng)一個ActivityRecord起宽,來記錄Activity的狀態(tài)以及其他的管理信息。其實(shí)就是服務(wù)器端的Activity對象的映像济榨。
TaskRecord:AMS抽象出來的一個“任務(wù)”的概念坯沪,是記錄ActivityRecord的棧,一個“Task”包含若干個ActivityRecord擒滑。AMS用TaskRecord確保Activity啟動和退出的順序腐晾。
介紹完這些,我們開始進(jìn)入正題
Activity的啟動過程
Activity啟動最終會調(diào)用到startActivityForResult方法丐一,我們只需要關(guān)注mParent == null中的邏輯即可藻糖。mParent代表的是ActivityGroup,其最開始是為了在一個界面中嵌入多個子Activity库车,在API13的時候就已經(jīng)廢棄了巨柒,可以使用Fragment表示一個界面的多個區(qū)域。
# android.app.ActivitypublicvoidstartActivityForResult(@RequiresPermission Intent intent,intrequestCode,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @Nullable Bundle options){if(mParent == null) {? ? ? ? Instrumentation.ActivityResult ar =? ? ? ? ? ? ? ? mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken,this,? ? ? ? ? ? ? ? ? ? ? ? intent, requestCode, options);if(ar != null) {? ? ? ? ? ? mMainThread.sendActivityResult(? ? ? ? ? ? ? ? ? ? mToken, mEmbeddedID, requestCode, ar.getResultCode(),? ? ? ? ? ? ? ? ? ? ar.getResultData());? ? ? ? }? ? ? ? ...? ? }else{? ? ? ? ...? ? }}
調(diào)用了Instrumentation的execStartActivity方法凝颇,在這里通過ActivityManagerNative.getDefault()方法獲取ActivityManagerService的一個本地代理對象ActivityManagerProxy潘拱,然后調(diào)用了其startActivity方法:
# android.app.InstrumentationpublicActivityResult execStartActivity(? ? ? ? Context who, IBinder contextThread, IBinder token, Activity target,? ? ? ? Intent intent, int requestCode, Bundle options) {? ? IApplicationThread whoThread = (IApplicationThread) contextThread;? ? ...try{? ? ? ...? ? ? ? int result = ActivityManagerNative.getDefault()? ? ? ? ? ? ? ? .startActivity(whoThread, who.getBasePackageName(), intent,? ? ? ? ? ? ? ? ? ? ? ? intent.resolveTypeIfNeeded(who.getContentResolver()),? ? ? ? ? ? ? ? ? ? ? ? token, target !=null? target.mEmbeddedID :null,? ? ? ? ? ? ? ? ? ? ? ? requestCode,0,null, options);? ? ? ? checkStartActivityResult(result, intent);? ? }catch(RemoteException e) {thrownewRuntimeException("Failure from system", e);? ? }returnnull;}
我們看一下ActivityManagerNative,繼承了Binder并實(shí)現(xiàn)了IActivityManager接口拧略,ActivityManagerService就是繼承了ActivityManagerNative芦岂。
publicabstractclassActivityManagerNativeextendsBinderimplementsIActivityManager
publicfinalclassActivityManagerServiceextendsActivityManagerNativeimplementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback
classActivityManagerProxyimplementsIActivityManager
ActivityManagerNative實(shí)際上獲取的就是其內(nèi)部類ActivityManagerProxy對象。ActivityManagerProxy只是ActivityManagerService的本地代理對象垫蛆,其startActivity方法會調(diào)用到AMS的startActivity方法禽最。而且要注意,這個startActivity方法會把ApplicationThread對象傳遞到AMS所在進(jìn)程袱饭,當(dāng)然了AMS拿到的實(shí)際上是ApplicationThread的代理對象ApplicationThreadProxy川无,AMS就要通過這個代理對象與我們的App進(jìn)程進(jìn)行通信。
# android.app.ActivityManagerNativeprivatestaticfinalSingleton gDefault =newSingleton() {protectedIActivityManager create() {? ? ? ? IBinder b = ServiceManager.getService("activity");if(false) {? ? ? ? ? ? Log.v("ActivityManager","default service binder = "+ b);? ? ? ? }? ? ? ? IActivityManager am = asInterface(b);if(false) {? ? ? ? ? ? Log.v("ActivityManager","default service = "+ am);? ? ? ? }returnam;? ? }};staticpublicIActivityManager asInterface(IBinder obj) {if(obj ==null) {returnnull;? ? }? ? IActivityManager in =? ? ? ? ? ? (IActivityManager)obj.queryLocalInterface(descriptor);if(in !=null) {returnin;? ? }returnnewActivityManagerProxy(obj);}staticpublicIActivityManager getDefault() {returngDefault.get();}
注:在Android8.0虑乖,由于使用AIDL的方式來寫ActivityManagerService懦趋,ActivityManagerNative已經(jīng)過期。
我們接著看一下AMS的startActivity方法:
# com.android.server.am.ActivityManagerServicepublicfinalintstartActivity(IApplicationThread caller, String callingPackage,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Intent intent, String resolvedType, IBinder resultTo, String resultWho,intrequestCode,intstartFlags, ProfilerInfo profilerInfo, Bundle bOptions){returnstartActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,? ? ? ? ? ? resultWho, requestCode, startFlags, profilerInfo, bOptions,? ? ? ? ? ? UserHandle.getCallingUserId());}
startActivity方法緊接著調(diào)用了其startActivityAsUser方法疹味。
@OverridepublicfinalintstartActivityAsUser(IApplicationThread caller, String callingPackage,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Intent intent, String resolvedType, IBinder resultTo, String resultWho,intrequestCode,intstartFlags, ProfilerInfo profilerInfo, Bundle bOptions,intuserId){? ? enforceNotIsolatedCaller("startActivity");? ? userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),? ? ? ? ? ? userId,false, ALLOW_FULL_ONLY,"startActivity",null);//TODO:Switch to user app stacks here.returnmActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,? ? ? ? ? ? resolvedType,null,null, resultTo, resultWho, requestCode, startFlags,? ? ? ? ? ? profilerInfo,null,null, bOptions,false, userId,null,null);}
接著調(diào)用了ActivityStarter的startActivityMayWait方法仅叫,由于方法很長,我們只保留關(guān)鍵的流程部分:
# com.android.server.am.ActivityStarterfinalintstartActivityMayWait(IApplicationThread caller,intcallingUid,? ? ? ? String callingPackage, Intent intent, String resolvedType,? ? ? ? IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,? ? ? ? IBinder resultTo, String resultWho,intrequestCode,intstartFlags,? ? ? ? ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,? ? ? ? Bundle bOptions, boolean ignoreTargetSecurity,intuserId,? ? ? ? IActivityContainer iContainer, TaskRecord inTask){? ? ? ? ? ...intres = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,? ? ? ? ? ? ? ? aInfo, rInfo, voiceSession, voiceInteractor,? ? ? ? ? ? ? ? resultTo, resultWho, requestCode, callingPid,? ? ? ? ? ? ? ? callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,? ? ? ? ? ? ? ? options, ignoreTargetSecurity, componentSpecified, outRecord, container,? ? ? ? ? ? ? ? inTask);? ? ? ? ...? ? }}
ActivityStarter調(diào)用了自身的startActivityLocked方法糙捺,這又是一個很長的方法诫咱,保留關(guān)鍵的流程如下。
# com.android.server.am.ActivityStarterfinalintstartActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,? ? ? ? String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,? ? ? ? IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,? ? ? ? IBinder resultTo, String resultWho,intrequestCode,intcallingPid,intcallingUid,? ? ? ? String callingPackage,intrealCallingPid,intrealCallingUid,intstartFlags,? ? ? ? ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,? ? ? ? ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,? ? ? ? TaskRecord inTask){interr = ActivityManager.START_SUCCESS;? ? ...try{? ? ? ? mService.mWindowManager.deferSurfaceLayout();? ? ? ? err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,true, options, inTask);? ? } finally {? ? ? ? mService.mWindowManager.continueSurfaceLayout();? ? }? ? postStartActivityUncheckedProcessing(r, err,stack.mStackId, mSourceRecord, mTargetStack);returnerr;}
ActivityStarter又調(diào)用了自身的startActivityUnchecked方法洪灯,
# com.android.server.am.ActivityStarterprivateintstartActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,? ? ? ? IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,intstartFlags, boolean doResume, ActivityOptions options, TaskRecord inTask){? ? ...if(mDoResume) {? ? ? ? ...if(!mTargetStack.isFocusable()? ? ? ? ? ? ...? ? ? ? }else{? ? ? ? ? ? mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,? ? ? ? ? ? ? ? ? ? mOptions);? ? ? ? }? ? }else{? ? ? ...? ? }? ? ...returnSTART_SUCCESS;}
在ActivityStarter中調(diào)用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法坎缭。
# com.android.server.am.ActivityStackSupervisorbooleanresumeFocusedStackTopActivityLocked(
? ? ? ? ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions){if(targetStack != null && isFocusedStack(targetStack)) {returntargetStack.resumeTopActivityUncheckedLocked(target, targetOptions);? ? }? ? ... }
在ActivityStackSupervisor的resumeFocusedStackTopActivityLocked中又調(diào)用了ActivityStack的resumeTopActivityUncheckedLocked方法。
# com.android.server.am.ActivityStackbooleanresumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options){? ...? ? boolean result =false;try{// Protect against recursion.mStackSupervisor.inResumeTopActivity =true;? ? ? ? ...? ? ? ? result = resumeTopActivityInnerLocked(prev, options);? ? } finally {? ? ? ? mStackSupervisor.inResumeTopActivity =false;? ? }returnresult;}
ActivityStack在resumeTopActivityUncheckedLocked又調(diào)用了其自身的resumeTopActivityInnerLocked方法。
# com.android.server.am.ActivityStackprivatebooleanresumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options){? ? ..// We need to start pausing the current activity so the top one can be resumed......if(mResumedActivity != null) {if(DEBUG_STATES) Slog.d(TAG_STATES,"resumeTopActivityLocked: Pausing "+ mResumedActivity);? ? ? ? pausing |= startPausingLocked(userLeaving,false, next, dontWaitForPause);? ? }? ? ...}
由于當(dāng)前的Activity執(zhí)行了onResume掏呼,所以mResumedActivity != null 條件滿足坏快,就會調(diào)用startPausingLocked方法先暫停當(dāng)前的Activity。注意:這個過程必然是一個IPC過程哄尔。我們看一下startPausingLocked方法假消。
# com.android.server.am.ActivityStackfinalboolean startPausingLocked(boolean userLeaving, boolean uiSleeping,? ? ? ? ActivityRecord resuming, boolean dontWait) {? ? ActivityRecord prev = mResumedActivity;? ? ...if(prev.app !=null&& prev.app.thread !=null) {if(DEBUG_PAUSE) Slog.v(TAG_PAUSE,"Enqueueing pending pause: "+ prev);try{? ? ? ? ? ? ...? ? ? ? ? ? prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,? ? ? ? ? ? ? ? ? ? userLeaving, prev.configChangeFlags, dontWait);? ? ? ? }catch(Exceptione) {? ? ? ? ? ...? ? ? ? }? ? }else{? ? ? ...? ? }? ? ...}
prev.app.thread表示的是IApplicationThread對象,在這里就是指的發(fā)起啟動的Activity所在進(jìn)程的ApplicationThread的本地代理ApplicationThreadProxy岭接。調(diào)用它的schedulePauseActivity方法,很明顯是一次IPC過程臼予,最終調(diào)用到server端鸣戴,也就是發(fā)起啟動的Activity所在進(jìn)程ApplicationThread的schedulePauseActivity方法。
# android.app.ActivityThread$$ApplicationThreadpublicfinalvoidschedulePauseActivity(IBinder token, boolean finished,? ? ? ? boolean userLeaving,intconfigChanges, boolean dontReport){intseq = getLifecycleSeq();if(DEBUG_ORDER) Slog.d(TAG,"pauseActivity "+ ActivityThread.this+" operation received seq: "+ seq);? ? sendMessage(? ? ? ? ? ? finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,? ? ? ? ? ? token,? ? ? ? ? ? (userLeaving ? USER_LEAVING :0) | (dontReport ? DONT_REPORT :0),? ? ? ? ? ? configChanges,? ? ? ? ? ? seq);}
通過Hander的轉(zhuǎn)發(fā)粘拾,接著會調(diào)用到ActivityThread的handlePauseActivity方法窄锅。
# android.app.ActivityThreadprivatevoidhandlePauseActivity(IBinder token, boolean finished,? ? ? ? boolean userLeaving,intconfigChanges, boolean dontReport,intseq){? ? ActivityClientRecord r = mActivities.get(token);? ? ...if(r != null) {? ? ...? ? ? ? performPauseActivity(token, finished, r.isPreHoneycomb(),"handlePauseActivity");? ? ...// Tell the activity manager we have paused.if(!dontReport) {try{? ? ? ? ? ? ? ? ActivityManagerNative.getDefault().activityPaused(token);? ? ? ? ? ? }catch(RemoteException ex) {throwex.rethrowFromSystemServer();? ? ? ? ? ? }? ? ? ? }? ? ? ? mSomeActivitiesChanged =true;? ? }}
在ActivityThread的handlePauseActivity中,首先會調(diào)用performPauseActivity來暫停當(dāng)前的Activity缰雇,經(jīng)過層層調(diào)用入偷,會調(diào)用到Intrumentation的callActivityOnPause方法,最終調(diào)用Activity的onPause方法械哟,這一塊的流程比較簡單疏之,在這里就不再詳細(xì)分析了,感興趣的可以自己研究下暇咆。
暫停之后锋爪,會調(diào)動ActivityManagerNative.getDefault().activityPaused(token),這個很明顯又是一次IPC過程爸业,就是告訴AMS其骄,已經(jīng)暫停當(dāng)前的Activity,可以啟動新的Activity 了扯旷。
我們來看一下AMS的的activityPaused方法:
# com.android.server.am.ActivityManagerService@OverridepublicfinalvoidactivityPaused(IBinder token){? ? finallongorigId = Binder.clearCallingIdentity();? ? synchronized(this) {? ? ? ? ActivityStackstack= ActivityRecord.getStackLocked(token);if(stack!= null) {stack.activityPausedLocked(token,false);? ? ? ? }? ? }? ? Binder.restoreCallingIdentity(origId);}
AMS中的activityPaused又調(diào)用了ActivityStack的activityPausedLocked方法拯爽。
# com.android.server.am.ActivityStackfinalvoid activityPausedLocked(IBinder token, boolean timeout) {? ? ...finalActivityRecord r = isInStackLocked(token);if(r !=null) {? ? ? ? mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);if(mPausingActivity == r) {if(DEBUG_STATES) Slog.v(TAG_STATES,"Moving to PAUSED: "+ r? ? ? ? ? ? ? ? ? ? + (timeout ?" (due to timeout)":" (pause complete)"));? ? ? ? ? ? completePauseLocked(true,null);return;? ? ? ? }else{? ? ? ? ? ...? ? ? ? }? ? }? ...}
在這個方法中又調(diào)用了ActivityStack自身的completePauseLocked方法,
# com.android.server.am.ActivityStackprivatevoidcompletePauseLocked(boolean resumeNext, ActivityRecord resuming){? ? ActivityRecord prev = mPausingActivity;if(resumeNext) {? ? ? ? final ActivityStack topStack = mStackSupervisor.getFocusedStack();if(!mService.isSleepingOrShuttingDownLocked()) {? ? ? ? ? ? mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);? ? ? ? }else{? ? ? ? ? ...? ? ? ? }? ? }? ? ...}
然后又調(diào)用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法钧忽,這視乎又重新調(diào)用了一遍毯炮,真復(fù)雜啊。
這個流程我們上面講過了惰瓜,ActivityStackSupervisor會繼續(xù)調(diào)用ActivityStack的resumeTopActivityUncheckedLocked方法否副,然后ActivityStack又調(diào)用其resumeTopActivityInnerLocked方法,調(diào)來調(diào)去崎坊,又到這個方法里面了备禀,上次在這里是執(zhí)行了前一個Activity的onPause方法。這次會調(diào)用到ActivityStackSupersivor的startSpecificActivityLocked方法。
# com.android.server.am.ActivityStackprivateboolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {// We need to start pausing the current activity so the top one can be resumed...finalboolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) !=0;? ? boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, dontWaitForPause);if(mResumedActivity !=null) {if(DEBUG_STATES) Slog.d(TAG_STATES,"resumeTopActivityLocked: Pausing "+ mResumedActivity);? ? ? ? pausing |= startPausingLocked(userLeaving,false, next, dontWaitForPause);? ? }? ? ...? ? ActivityStack lastStack = mStackSupervisor.getLastStack();if(next.app !=null&& next.app.thread !=null) {? ? ? ? ...? ? }else{? ? ? ? ...? ? ? ? mStackSupervisor.startSpecificActivityLocked(next,true,true);? ? }if(DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();returntrue;}
分析到這里曲尸,好像我們的就要開始啟動我們的目標(biāo)Activity了赋续,好激動有木有!
在ActivityStackSupersivor的startSpecificActivityLocked方法中會判斷Activity所在進(jìn)程是否存在另患,如果不存在的話就要創(chuàng)建一個新的進(jìn)程纽乱。在這里,我們是Activity啟動其App內(nèi)部的另一個Activity昆箕,所以進(jìn)程肯定是存在的鸦列,會走到realStartActivityLocked方法中。
# com.android.server.am.ActivityStackSupervisorvoidstartSpecificActivityLocked(ActivityRecord r,
? ? ? ? boolean andResume, boolean checkConfig){? ? ...if(app != null && app.thread != null) {try{? ? ...? ? ? ? ? ? realStartActivityLocked(r, app, andResume, checkConfig);return;? ? ? ? }catch(RemoteException e) {? ? ? ? ? ...? ? ? ? }? ? }? ? mService.startProcessLocked(r.processName, r.info.applicationInfo,true,0,"activity", r.intent.getComponent(),false,false,true);}
再來看一下ActivityStackSupersivor的realStartActivityLocked方法鹏倘,這次似乎真的要啟動一個Activity了薯嗤。
# com.android.server.am.ActivityStackSupervisorfinal booleanrealStartActivityLocked(ActivityRecord r, ProcessRecord app,
? ? ? ? boolean andResume, boolean checkConfig)throws RemoteException{? ? ...try{? ? ? ? app.thread.scheduleLaunchActivity(newIntent(r.intent), r.appToken,? ? ? ? ? ? ? ? System.identityHashCode(r), r.info,newConfiguration(mService.mConfiguration),newConfiguration(task.mOverrideConfig), r.compat, r.launchedFromPackage,? ? ? ? ? ? ? ? task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,? ? ? ? ? ? ? ? newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);? ? ? ...? ? }catch(RemoteException e) {? ? ? ...? ? }? ? ...returntrue;}
看了代碼,果然纤泵,調(diào)用了app.thread.scheduleLaunchActivity方法骆姐,app.thread我們前面講過,就是IApplicationThread對象捏题,實(shí)際上就是ApplicationThreadProxy對象玻褪,經(jīng)過IPC過程會調(diào)用到ApplicationThread的scheduleLaunchActivity方法,我們來看一下:
# android.app.ActivityThread$$ApplicationThread@OverridepublicfinalvoidscheduleLaunchActivity(Intent intent, IBinder token,intident,? ? ? ? ActivityInfo info, Configuration curConfig, Configuration overrideConfig,? ? ? ? CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,intprocState, Bundle state, PersistableBundle persistentState,? ? ? ? List pendingResults, List pendingNewIntents,? ? ? ? boolean notResumed, boolean isForward, ProfilerInfo profilerInfo){? ? ...? ? sendMessage(H.LAUNCH_ACTIVITY, r);}
通過Hander的轉(zhuǎn)發(fā)公荧,接著會調(diào)用到ActivityThread的handlePauseActivity方法带射。
# android.app.ActivityThreadprivatevoidhandleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason){? ? ...? ? Activity a = performLaunchActivity(r, customIntent);if(a != null) {? ? ...? ? ? ? handleResumeActivity(r.token,false, r.isForward,? ? ? ? ? ? ? ? !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);? ? ? ...? ? }else{? ? ? ...? ? }}
handlePauseActivity內(nèi)部調(diào)用performLaunchActivity方法:
# android.app.ActivityThreadprivateActivity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {? ? ...? ? Activity activity =null;try{? ? ? ? java.lang.ClassLoader cl = r.packageInfo.getClassLoader();? ? ? ? activity = mInstrumentation.newActivity(? ? ? ? ? ? ? ? cl, component.getClassName(), r.intent);? ? ? ? ...? ? }catch(Exceptione) {? ? ? ...? ? }try{? ? ? ? Application app = r.packageInfo.makeApplication(false, mInstrumentation);? ? ? ? ...if(activity !=null) {? ? ? ? ? ? Context appContext = createBaseContextForActivity(r, activity);? ? ? ? ? ? ...? ? ? ? ? ? activity.attach(appContext, this, getInstrumentation(), r.token,? ? ? ? ? ? ? ? ? ? r.ident, app, r.intent, r.activityInfo, title, r.parent,? ? ? ? ? ? ? ? ? ? r.embeddedID, r.lastNonConfigurationInstances, config,? ? ? ? ? ? ? ? ? ? r.referrer, r.voiceInteractor, window);? ? ? ? ? ? ...? ? ? ? ? ? activity.mCalled =false;if(r.isPersistable()) {? ? ? ? ? ? ? ? mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);? ? ? ? ? ? }else{? ? ? ? ? ? ? ? mInstrumentation.callActivityOnCreate(activity, r.state);? ? ? ? ? ? }? ? ? ? ? ...? ? ? ? ? ? r.activity = activity;? ? ? ? ? ? r.stopped =true;if(!r.activity.mFinished) {? ? ? ? ? ? ? ? activity.performStart();? ? ? ? ? ? ? ? r.stopped =false;? ? ? ? ? ? }if(!r.activity.mFinished) {if(r.isPersistable()) {if(r.state !=null|| r.persistentState !=null) {? ? ? ? ? ? ? ? ? ? ? ? mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? r.persistentState);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }elseif(r.state !=null) {? ? ? ? ? ? ? ? ? ? mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);? ? ? ? ? ? ? ? }? ? ? ? ? ? }if(!r.activity.mFinished) {? ? ? ? ? ? ? ? activity.mCalled =false;if(r.isPersistable()) {? ? ? ? ? ? ? ? ? ? mInstrumentation.callActivityOnPostCreate(activity, r.state,? ? ? ? ? ? ? ? ? ? ? ? ? ? r.persistentState);? ? ? ? ? ? ? ? }else{? ? ? ? ? ? ? ? ? ? mInstrumentation.callActivityOnPostCreate(activity, r.state);? ? ? ? ? ? ? ? }if(!activity.mCalled) {thrownewSuperNotCalledException("Activity "+ r.intent.getComponent().toShortString() +" did not call through to super.onPostCreate()");? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? ? ? r.paused =true;? ? ? ? mActivities.put(r.token, r);? ? }catch(SuperNotCalledException e) {throwe;? ? }catch(Exceptione) {? ? ? ...? ? }returnactivity;}
在performLaunchActivity內(nèi)部,創(chuàng)建了Activity對象稚矿,并調(diào)用了activity的attach方法庸诱,在這個方法中綁定一些屬性,并且創(chuàng)建了Activity所屬的Window對象晤揣。接著Instrumentation會調(diào)用callActivityOnCreate桥爽、callActivityOnRestoreInstanceState、callActivityOnPostCreate等來完成Activity生命周期的回調(diào)昧识。不過有一點(diǎn)很有意思钠四,在這個方法中Activity自己調(diào)用了其performStart方法,但這個方法內(nèi)部又調(diào)用了Instrumentation的callActivityOnStart方法跪楞,進(jìn)而又調(diào)用了Activity的onStart方法缀去。繞過來繞過去,總之甸祭,Activity生命周期方法的調(diào)用均是通過Instrumentation來控制的缕碎。
至此,Activity的啟動過程算是分析完了池户,太費(fèi)腦筋了咏雌,需要來一瓶營養(yǎng)快線補(bǔ)補(bǔ)身體凡怎。流程太多,不好記赊抖,但是有句話說的好 "一圖勝千言"统倒,下面我們來看一下Activity啟動的一個時序圖。
Activity啟動過程.png
總結(jié)
源碼分析過程是比較繞氛雪,比較燒腦的過程房匆,不要太糾結(jié)去API的調(diào)用,盡量側(cè)重流程报亩。分析源碼浴鸿,最好帶著問題去分析,不要為了分析而分析捆昏,盡量在分析過程中尋找自己想要的答案赚楚。比如:
Activity對象是怎么創(chuàng)建的?
Window對象是什么時候創(chuàng)建的骗卜?
LayoutInflater什么時候創(chuàng)建的?
為什么在Activity中的布局中或者Fragment的中View獲取的Context都是其所在的Activity對象左胞?
為什么自定義View一定要有兩個參數(shù)的構(gòu)造函數(shù)寇仓?
Activity的生命周期方法是被誰回調(diào)的?
Application是什么時候創(chuàng)建的烤宙?
ClassLoader對象是什么時候創(chuàng)建的遍烦?
子線程可以啟動Activity、Service嗎躺枕?
下拉通知欄服猪,會影響Activity生命周期嗎?
筆者初入Android開發(fā)沒多久的時候拐云,有次面試罢猪,面試官問我在子線程中啟動Activity可以嗎?我回答可以叉瘩,因?yàn)槲以囘^膳帕,但是問我為什么我卻不知道。如果那時候看了Activity啟動過程的源碼薇缅,看了Binder機(jī)制的話危彩,應(yīng)該很容易的就回答出來了。