Activity启动过程分析
通常我们在Activity中启动一个另一个Activity,就是调用Activity的startActivity方法,这个最终会调用到Activity的startActivityForResult方法。那你有没有想过Activity的启动到底经历了哪些过程,我们今天就来分析一下。
在具体分析之前,要先说明一下,Activity的启动流程在细节挺繁琐的,比如启动另一个App的Activity或者启动不同的launchMode的Activity,在细节上都会有不同。我们这次的源码分析着重分析一下流程,为了简单起见,就以分析一个Activity启动app内部另一个standard模式的Activity为主。
Activity启动另一个Activity之前,当前的Activity先要执行onPause,被启动的Activity才会执行到onResume方法。这中间实际上是会执行4次IPC过程的:
当前Activity发起启动另一个Activity的请求——>ActivityManagerService
ActivityManagerService——> 通知App暂停当前Activity
当前App告知已经暂停了当前的Activity——> ActivityManagerService
ActivityManagerService ——> 通知App启动新的Activity
注:本次源码分析采用Android7.0,不同版本的源码在细节上会有不同,比如,在Android8.0上ActivityManagerService就改成了以AIDL的方式来写,请不要太纠结API的不同。
注:本文Activity启动过程源码分析过程比较长,代码较繁琐,请做好心理准备。
Activity启动涉及到的类
首先要简单介绍一下Activity启动过程涉及到的类,以便于更好的理解这个启动过程。
ActivityThread:App启动的入口
ApplicationThread:ActivityThread的内部类,继承Binder,可以进程跨进程通信。
ApplicationThreadProxy:ApplicationThread的一个本地代理,其它的client端通过这个对象调用server端ApplicationThread中方法。
Instrumentation:负责发起Activity的启动、并具体负责Activity的创建以及Activity生命周期的回调。一个应用进程只会有一个Instrumentation对象,App内的所有Activity都持有该对象的引用。
ActivityManagerService:简称AMS,是service端对象,负责管理系统中所有的Activity
ActivityManagerProxy:是ActivityManagerService的本地代理
ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
ActivityRecord:ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。
TaskRecord:AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。
介绍完这些,我们开始进入正题
Activity的启动过程
Activity启动最终会调用到startActivityForResult方法,我们只需要关注mParent == null中的逻辑即可。mParent代表的是ActivityGroup,其最开始是为了在一个界面中嵌入多个子Activity,在API13的时候就已经废弃了,可以使用Fragment表示一个界面的多个区域。
# 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{ ... }}
调用了Instrumentation的execStartActivity方法,在这里通过ActivityManagerNative.getDefault()方法获取ActivityManagerService的一个本地代理对象ActivityManagerProxy,然后调用了其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并实现了IActivityManager接口,ActivityManagerService就是继承了ActivityManagerNative。
publicabstractclassActivityManagerNativeextendsBinderimplementsIActivityManager
publicfinalclassActivityManagerServiceextendsActivityManagerNativeimplementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback
classActivityManagerProxyimplementsIActivityManager
ActivityManagerNative实际上获取的就是其内部类ActivityManagerProxy对象。ActivityManagerProxy只是ActivityManagerService的本地代理对象,其startActivity方法会调用到AMS的startActivity方法。而且要注意,这个startActivity方法会把ApplicationThread对象传递到AMS所在进程,当然了AMS拿到的实际上是ApplicationThread的代理对象ApplicationThreadProxy,AMS就要通过这个代理对象与我们的App进程进行通信。
# 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已经过期。
我们接着看一下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方法紧接着调用了其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);}
接着调用了ActivityStarter的startActivityMayWait方法,由于方法很长,我们只保留关键的流程部分:
# 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调用了自身的startActivityLocked方法,这又是一个很长的方法,保留关键的流程如下。
# 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又调用了自身的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中调用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法。
# com.android.server.am.ActivityStackSupervisorbooleanresumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions){if(targetStack != null && isFocusedStack(targetStack)) {returntargetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } ... }
在ActivityStackSupervisor的resumeFocusedStackTopActivityLocked中又调用了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又调用了其自身的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); } ...}
由于当前的Activity执行了onResume,所以mResumedActivity != null 条件满足,就会调用startPausingLocked方法先暂停当前的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对象,在这里就是指的发起启动的Activity所在进程的ApplicationThread的本地代理ApplicationThreadProxy。调用它的schedulePauseActivity方法,很明显是一次IPC过程,最终调用到server端,也就是发起启动的Activity所在进程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的转发,接着会调用到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中,首先会调用performPauseActivity来暂停当前的Activity,经过层层调用,会调用到Intrumentation的callActivityOnPause方法,最终调用Activity的onPause方法,这一块的流程比较简单,在这里就不再详细分析了,感兴趣的可以自己研究下。
暂停之后,会调动ActivityManagerNative.getDefault().activityPaused(token),这个很明显又是一次IPC过程,就是告诉AMS,已经暂停当前的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又调用了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{ ... } } ...}
在这个方法中又调用了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{ ... } } ...}
然后又调用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法,这视乎又重新调用了一遍,真复杂啊。
这个流程我们上面讲过了,ActivityStackSupervisor会继续调用ActivityStack的resumeTopActivityUncheckedLocked方法,然后ActivityStack又调用其resumeTopActivityInnerLocked方法,调来调去,又到这个方法里面了,上次在这里是执行了前一个Activity的onPause方法。这次会调用到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;}
分析到这里,好像我们的就要开始启动我们的目标Activity了,好激动有木有!
在ActivityStackSupersivor的startSpecificActivityLocked方法中会判断Activity所在进程是否存在,如果不存在的话就要创建一个新的进程。在这里,我们是Activity启动其App内部的另一个Activity,所以进程肯定是存在的,会走到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;}
看了代码,果然,调用了app.thread.scheduleLaunchActivity方法,app.thread我们前面讲过,就是IApplicationThread对象,实际上就是ApplicationThreadProxy对象,经过IPC过程会调用到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的转发,接着会调用到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内部调用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内部,创建了Activity对象,并调用了activity的attach方法,在这个方法中绑定一些属性,并且创建了Activity所属的Window对象。接着Instrumentation会调用callActivityOnCreate、callActivityOnRestoreInstanceState、callActivityOnPostCreate等来完成Activity生命周期的回调。不过有一点很有意思,在这个方法中Activity自己调用了其performStart方法,但这个方法内部又调用了Instrumentation的callActivityOnStart方法,进而又调用了Activity的onStart方法。绕过来绕过去,总之,Activity生命周期方法的调用均是通过Instrumentation来控制的。
至此,Activity的启动过程算是分析完了,太费脑筋了,需要来一瓶营养快线补补身体。流程太多,不好记,但是有句话说的好 "一图胜千言",下面我们来看一下Activity启动的一个时序图。
Activity启动过程.png
总结
源码分析过程是比较绕,比较烧脑的过程,不要太纠结去API的调用,尽量侧重流程。分析源码,最好带着问题去分析,不要为了分析而分析,尽量在分析过程中寻找自己想要的答案。比如:
Activity对象是怎么创建的?
Window对象是什么时候创建的?
LayoutInflater什么时候创建的?
为什么在Activity中的布局中或者Fragment的中View获取的Context都是其所在的Activity对象?
为什么自定义View一定要有两个参数的构造函数?
Activity的生命周期方法是被谁回调的?
Application是什么时候创建的?
ClassLoader对象是什么时候创建的?
子线程可以启动Activity、Service吗?
下拉通知栏,会影响Activity生命周期吗?
笔者初入Android开发没多久的时候,有次面试,面试官问我在子线程中启动Activity可以吗?我回答可以,因为我试过,但是问我为什么我却不知道。如果那时候看了Activity启动过程的源码,看了Binder机制的话,应该很容易的就回答出来了。
网友评论