快捷搜索:  汽车  科技

android activity启动流程,Android常用组件Activity启动详细流程

android activity启动流程,Android常用组件Activity启动详细流程ActvityiManagerService.startActivityAsUser() ActivityStackSupervisor.startActivityMayWait() ActivityStackSupervisor.startActivityLocked() ActivityStackSupervisor.startActivityUncheckedLocked() ActivityStackSupervisor.startActivityLocked() ActivityStackSupervisor.resumeTopActivitiesLocked() ActivityStackSupervisor.resumeTopActivityInnerLocked()<pre spellcheck="false" class="md-fences

一、Activity请求启动

android activity启动流程,Android常用组件Activity启动详细流程(1)

我们以startActivity这种来分析

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n6" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Intent intent=new Intent(MainActivity.this TargetActivity.class); startActivity(intent);</pre>

经过startActivity-->startActivityForResult-->execStartActivity 最终会调用Instrumentation的execStartActivity方法

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n8" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public ActivityResult execStartActivity( Context who IBinder contextThread IBinder token Activity target Intent intent int requestCode Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER referrer); } ..... try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(who); //获取AMS的代理,启动Activity int result = ActivityManagerNative.getDefault() .startActivity(whoThread who.getBasePackageName() intent intent.resolveTypeIfNeeded(who.getContentResolver()) token target != null ? target.mEmbeddedID : null requestCode 0 null options); //检查Activity是否启动成功,若失败给出是什么原因 checkStartActivityResult(result intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system" e); } return null; } }</pre>

这些参数的意思是:

  • this,为启动Activity的对象;
  • contextThread,为Binder对象,是主进程的context对象;
  • token,也是一个Binder对象,指向了服务端一个ActivityRecord对象;
  • target,为启动的Activity;
  • intent,启动的Intent对象;
  • requestCode,请求码;
  • options,参数;

先看checkStartActivityResult方法的实现

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n28" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public static void checkStartActivityResult(int res Object intent) { if (res >= ActivityManager.START_SUCCESS) { return; } switch (res) { case ActivityManager.START_INTENT_NOT_RESOLVED: case ActivityManager.START_CLASS_NOT_FOUND: if (intent instanceof Intent && ((Intent)intent).getComponent() != null) throw new ActivityNotFoundException( "Unable to find explicit activity class " ((Intent)intent).getComponent().toShortString() "; have you declared this activity in your AndroidManifest.xml?"); throw new ActivityNotFoundException( "No Activity found to handle " intent); case ActivityManager.START_PERMISSION_DENIED: throw new SecurityException("Not allowed to start activity " intent); case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: throw new AndroidRuntimeException( "FORWARD_RESULT_FLAG used while also requesting a result"); case ActivityManager.START_NOT_ACTIVITY: throw new IllegalArgumentException( "PendingIntent is not an activity"); case ActivityManager.START_NOT_VOICE_COMPATIBLE: throw new SecurityException( "Starting under voice control not allowed for: " intent); case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION: throw new IllegalStateException( "Session calling startVoiceActivity does not match active session"); case ActivityManager.START_VOICE_HIDDEN_SESSION: throw new IllegalStateException( "Cannot start voice activity on a hidden session"); case ActivityManager.START_CANCELED: throw new AndroidRuntimeException("Activity could not be started for " intent); default: throw new AndroidRuntimeException("Unknown error code " res " when starting " intent); } }</pre>

常见的ActivityNotFoundException,SecurityException等错日志就在这里报出来的;

OK,现在回到execStartActivity,内部调用了ActivityManagerNative.getDefault().startActivity,关于ActivityManagerNative已经说了很多了,相当于AMS服务端存根或者代理,其客户端是ActivityManagerNative的内部类ActivityManagerProxy,这里getDefault获取的就是ActivityManagerProxy对象,通过ActivityManagerProxy对象来使用AMS内部的一些服务,包括单不限于启动Activity

所以通过ActivityManagerProxy对象调用startActivity方法的实质是调用BinderProxy.transact向Binder驱动发送START_ACTIVITY_TRACSACTION命令,binder驱动将处理逻辑从Launcher所在的进程切换到AMS所在的SystemServer进程。OK,我们直接看ActivityManagerService的startActivity方法,不明白,建议看一下Binder的通信原理。

二、AMS处理Activity的启动请求2.1、AMS处理Activity的启动请求

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n33" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> @Override public final int startActivity(IApplicationThread caller String callingPackage Intent intent String resolvedType IBinder resultTo String resultWho int requestCode int startFlags ProfilerInfo profilerInfo Bundle bOptions) { return startActivityAsUser(caller callingPackage intent resolvedType resultTo resultWho requestCode startFlags profilerInfo bOptions UserHandle.getCallingUserId()); }</pre>

保持篇幅,以下步骤省略

ActvityiManagerService.startActivityAsUser() ActivityStackSupervisor.startActivityMayWait() ActivityStackSupervisor.startActivityLocked() ActivityStackSupervisor.startActivityUncheckedLocked() ActivityStackSupervisor.startActivityLocked() ActivityStackSupervisor.resumeTopActivitiesLocked() ActivityStackSupervisor.resumeTopActivityInnerLocked()

在resumeTopActivityInnerLocked的内部有如下代码

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n38" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES "resumeTopActivityLocked: Pausing " mResumedActivity); pausing |= startPausingLocked(userLeaving false true dontWaitForPause); } </pre>

这表明在启动一个Activity的时候,前面一个Activity要执行onPause方法,onPause方法是怎么调用的呢?

2.2、AMS调用栈顶Activity的onPause

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n41" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> final boolean startPausingLocked(boolean userLeaving boolean uiSleeping boolean resuming boolean dontWait) { ...... if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) { prev.updateThumbnailLocked(screenshotActivities(prev) null); } stopFullyDrawnTraceIfNeeded(); mService.updateCpuStats(); if (prev.app != null && prev.app.thread != null) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE "Enqueueing pending pause: " prev); try { //调用ApplicationThread的schedulePauseActivity prev.app.thread.schedulePauseActivity(prev.appToken prev.finishing userLeaving prev.configChangeFlags dontWait); } catch (Exception e) { ...... } } ...... }</pre>

这里先留一个问题, 我知道prev.app.thread是ApplicationThreadProxy对象,实际是调用了ApplicationThread的schedulePauseActivity方法,但是 AMS是怎么获取到prev.app.thread的呢?

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n43" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public final void schedulePauseActivity(IBinder token boolean finished boolean userLeaving int configChanges boolean dontReport) { sendMessage( finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY token (userLeaving ? 1 : 0) | (dontReport ? 2 : 0) configChanges); } </pre>

关键就是最后调用了sendMessage(H.BIND_APPLICATION data) 发送了消息; 关于H这个类,其实是个Hander,我觉得它的作用就像是一个交通枢纽;H接收到这个Message之后,调用

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n45" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> handlePauseActivity((IBinder)msg.obj false (msg.arg1&1) != 0 msg.arg2 (msg.arg1&2) != 0);</pre>

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n46" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> private void handlePauseActivity(IBinder token boolean finished boolean userLeaving int configChanges boolean dontReport) { ActivityClientRecord r = mActivities.get(token); ....... r.activity.mConfigChangeFlags |= configChanges; performPauseActivity(token finished r.isPreHoneycomb()); ....... // Tell the activity manager we have paused. if (!dontReport) { try { ActivityManagerNative.getDefault().activityPaused(token); } catch (RemoteException ex) { } } mSomeActivitiesChanged = true; } }</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n47" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> final Bundle performPauseActivity(ActivityClientRecord r boolean finished boolean saveState) { if (r.paused) { ....... try { ....... //调用Instrumentation的callActivityOnPause方法 mInstrumentation.callActivityOnPause(r.activity); EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED UserHandle.myUserId() r.activity.getComponentName().getClassName()); if (!r.activity.mCalled) { throw new SuperNotCalledException( "Activity " r.intent.getComponent().toShortString() " did not call through to super.onPause()"); } } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { ....... } } r.paused = true; ....... return !r.activity.mFinished && saveState ? r.state : null; }</pre>

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n48" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public void callActivityOnPause(Activity activity) { activity.performPause(); } </pre>

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n49" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> final void performPause() { mDoReportFullyDrawn = false; mFragments.dispatchPause(); mCalled = false; //onPause执行 onPause(); mResumed = false; if (!mCalled && getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.GINGERBREAD) { throw new SuperNotCalledException( "Activity " mComponent.toShortString() " did not call through to super.onPause()"); } mResumed = false; }</pre>

分析到这里 onPause()终于执行了; 回到 handlePauseActivity方法中,在这个方法最后调用了ActivityManagerNative.getDefault().activityPaused(token)

2.3、ActivityManagerService的activityPaused方法执行

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n52" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> @Override public final void activityPaused(IBinder token) { final long origId = Binder.clearCallingIdentity(); synchronized(this) { ActivityStack stack = ActivityRecord.getStackLocked(token); if (stack != null) { stack.activityPausedLocked(token false); } } Binder.restoreCallingIdentity(origId); }</pre>

经过一些方法,最终会调用startSpecificActivityLocked

ActivityStack.activityPausedLocked() ActivityStack.completePauseLocked() ActivityStackSupervisor.resumeTopActivitiesLocked() ActivityStack.resumeTopActivityLocked() ActivityStack.resumeTopActivityInnerLocked () ActivityStack.startSpecificActivityLocked ()

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n56" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> void startSpecificActivityLocked(ActivityRecord r boolean andResume boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName r.info.applicationInfo.uid true); r.task.stack.setLaunchTime(r); if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(r.info.packageName r.info.applicationInfo.versionCode mService.mProcessStats); } realStartActivityLocked(r app andResume checkConfig); return; } catch (RemoteException e) { Slog.w(TAG "Exception when starting activity " r.intent.getComponent().flattenToShortString() e); } // If a dead object exception was thrown -- fall through to // restart the application. } mService.startProcessLocked(r.processName r.info.applicationInfo true 0 "activity" r.intent.getComponent() false false true); } </pre>

如果需要启动的Activity所需要的应用进程是否已经启动,如果没有则执行realStartActivityLocked去启动Activity 否则去启动启动应用进程,相当于一个预启动的过程

2.4、应用进程创建

startProcessLocked是怎么执行的? SystemServer进程中Ams通过Socket与Zygote进程进行通信的,Zygote接收到AMS发起的创建进程的请求,会fork出一个子进程,并且反射调用这个进程中ActivityThread的main方法 在应用进程启动之后,ActivityThread的main方法就开始执行了

三、ActivityThread的main方法执行

在ActivityThread的main方法里调用thread.attach(false)

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n62" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER "ActivityThreadMain"); SamplingProfilerIntegration.start(); ...... Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }</pre>

对于上面main方法,相信很多人都看多很多遍了,接下来重点分析 thread.attach(false)这行代码

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n64" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { ....... //获取ActivityManagerService在客户端的代理 IActivityManager mgr = ActivityManagerNative.getDefault(); try { //实质是调用ActivityManagerService的attachApplication方法 目的是让ActivityManagerService通过ApplicationThread代理对象控制应用进程 mgr.attachApplication(mAppThread); } catch (RemoteException ex) { } } ....... }</pre>

在调用 mgr.attachApplication()的时候,将mAppThread对象传进去了

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n66" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> final ApplicationThread mAppThread = new ApplicationThread();</pre>

ApplicationThread继承了ApplicationThreadNative, 看一下ApplicationThreadNative里面的方法

内部调用了ActivityManagerNative.getDefault() .attachApplication,关于ActivityManagerNative已经说了很多了,相当于AMS服务端存根或者代理,其客户端是ActivityManagerNative的内部类ActivityManagerProxy,这里getDefault获取的就是ActivityManagerProxy对象,通过ActivityManagerProxy对象来使用AMS内部的一些服务,包括单不限于启动Activity

所以通过ActivityManagerProxy对象调用attachApplication方法的实质是调用BinderProxy.transact向Binder驱动发送ATTACH_APPLICATION_TRANSACTION命令,binder驱动将处理逻辑从APP应用进程所在的进程切换到AMS所在的SystemServer进程

OK,我们直接看ActivityManagerService的attachApplication方法:

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n69" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> @Override public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread callingPid); Binder.restoreCallingIdentity(origId); } }</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n70" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">private final boolean attachApplicationLocked(IApplicationThread thread int pid) { ProcessRecord app; if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { //通过进程ID,获取进程的记录信息 app = mPidsSelfLocked.get(pid); } } else { app = null; } if (app == null) { Slog.w(TAG "No pending application record for pid " pid " (IApplicationThread " thread "); dropping process"); EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS pid); if (pid > 0 && pid != MY_PID) { //如果没有获取到,需要杀死该进程,MY_PID是系统进程 Process.killProcessQuiet(pid); } else { ...... return false; } ...... //获取进程名称 final String processName = app.processName; try { AppDeathRecipient adr = new AppDeathRecipient( app pid thread); thread.asBinder().linkToDeath(adr 0); app.deathRecipient = adr; } catch (RemoteException e) { app.resetPackageList(mProcessStats); startProcessLocked(app "link fail" processName); return false; } EventLog.writeEvent(EventLogTags.AM_PROC_BOUND app.userId app.pid app.processName); //设置进程的OOM,adj等值 //还记得上面留下的那个问题吗,AMS是怎么获取到prev.app.thread的呢?就在这,prev.app是ProcessRecord对象,makeActive内部将thread对象赋值给prev.app.thread。可以自己查阅,这样AMS是可以查询进程记录的,进程记录中就有一个app.thread,若AMS要跟Activity通信直接获取prev.app.thread就可以了。 app.makeActive(thread mProcessStats); app.curAdj = app.setAdj = -100; app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT; app.forcingToForeground = null; updateProcessForegroundLocked(app false false); app.hasShownUi = false; app.debugging = false; app.cached = false; app.killedByAm = false; //将attach之前的超时Meessage移除掉 mHandler.removeMessages(PROC_START_TIMEOUT_MSG app); boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info); List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null; ...... try { ...... thread.bindApplication(processName appInfo providers app.instrumentationClass profilerInfo app.instrumentationArguments app.instrumentationWatcher app.instrumentationUiAutomationConnection testMode enableOpenGlTrace isRestrictedBackupMode || !normalMode app.persistent new Configuration(mConfiguration) app.compat getCommonServicesLocked(app.isolated) mCoreSettingsObserver.getCoreSettingsLocked()); updateLruProcessLocked(app false null); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { // todo: Yikes! What should we do? For now we will try to // start another process but that could easily get us in // an infinite loop of restarting processes... Slog.wtf(TAG "Exception thrown during bind of " app e); app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); startProcessLocked(app "bind fail" processName); return false; } ...... // See if the top visible activity is waiting to run in this process... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { Slog.wtf(TAG "Exception thrown launching activities in " app e); badApp = true; } } // 执行等待进程而暂时挂起的Service if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app processName); } catch (Exception e) { Slog.wtf(TAG "Exception thrown starting services in " app e); badApp = true; } } // 执行等待进程而暂时挂起的广播 if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { didSomething |= sendPendingBroadcastsLocked(app); } catch (Exception e) { // If the app died trying to launch the receiver we declare it 'bad' Slog.wtf(TAG "Exception thrown dispatching broadcasts in " app e); badApp = true; } } ...... if (!didSomething) { //调整进程优先级adj的值 updateOomAdjLocked(); } return true; }</pre>

发现AMS用IApplicationThread对象thread调用了bindApplication,thread实际上就是ApplicationThreadProxy对象; AMS通过ApplicationThreadProxy对象与ActivityThread通信。所以去ApplicationThread中看bindApplication的真正实现

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n72" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public final void bindApplication(String processName ApplicationInfo appInfo List<ProviderInfo> providers ComponentName instrumentationName ProfilerInfo profilerInfo Bundle instrumentationArgs IInstrumentationWatcher instrumentationWatcher IUiAutomationConnection instrumentationUiConnection int debugMode boolean enableOpenGlTrace boolean isRestrictedBackupMode boolean persistent Configuration config CompatibilityInfo compatInfo Map<String IBinder> services Bundle coreSettings) { if (services != null) { // Setup the service cache in the ServiceManager ServiceManager.initServiceCache(services); } setCoreSettings(coreSettings); ...... AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableOpenGlTrace = enableOpenGlTrace; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION data); }</pre>

这里又是用H发送了一个消息,是不是很像一个交通枢纽

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n74" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER "bindApplication"); AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); </pre>

handleBindApplication内部就不分析了,Applcation对象的onCreate方法调用就是在这里面,它内部创建了Applcation对象

四、Activity周期如何执行4.1、Activity的onCreate是怎么回调的

回到第二小节的startSpecificActivityLocked方法

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n79" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> void startSpecificActivityLocked(ActivityRecord r boolean andResume boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName r.info.applicationInfo.uid true); r.task.stack.setLaunchTime(r); if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { app.addPackage(r.info.packageName r.info.applicationInfo.versionCode mService.mProcessStats); } realStartActivityLocked(r app andResume checkConfig); return; } catch (RemoteException e) { Slog.w(TAG "Exception when starting activity " r.intent.getComponent().flattenToShortString() e); } // If a dead object exception was thrown -- fall through to // restart the application. } mService.startProcessLocked(r.processName r.info.applicationInfo true 0 "activity" r.intent.getComponent() false false true); }</pre>

在预启动之后,一般我们的应用进程就被孵化来了,直接执行realStartActivityLocked去启动Activity

在realStartActivityLocked内部调用了如下代码,现在你应该知道 app.thread是什么了

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n82" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> app.thread.scheduleLaunchActivity(new Intent(r.intent) r.appToken System.identityHashCode(r) r.info new Configuration(mService.mConfiguration) new Configuration(stack.mOverrideConfig) r.compat r.launchedFromPackage task.voiceInteractor app.repProcState r.icicle r.persistentState results newIntents !andResume mService.isNextTransitionForward() profilerInfo);</pre>

直接到scheduleLaunchActivity真正实现,它的真正实现是在Applciation中的

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n84" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public final void scheduleLaunchActivity(Intent intent IBinder token int ident ActivityInfo info Configuration curConfig Configuration overrideConfig CompatibilityInfo compatInfo String referrer IVoiceInteractor voiceInteractor int procState Bundle state PersistableBundle persistentState List<ResultInfo> pendingResults List<ReferrerIntent> pendingNewIntents boolean notResumed boolean isForward ProfilerInfo profilerInfo) { updateProcessState(procState false); ActivityClientRecord r = new ActivityClientRecord(); r.token = token; r.ident = ident; r.intent = intent; r.referrer = referrer; r.voiceInteractor = voiceInteractor; r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; r.persistentState = persistentState; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; r.profilerInfo = profilerInfo; r.overrideConfig = overrideConfig; updatePendingConfiguration(curConfig); sendMessage(H.LAUNCH_ACTIVITY r); } </pre>

经过一堆的变量赋值之后,又通过H发送了一个消息LAUNCH_ACTIVITY,H在收到这个消息之后,执行下面

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n86" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER "activityStart"); final ActivityClientRecord r = (ActivityClientRecord) msg.obj; r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo r.compatInfo); handleLaunchActivity(r null); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n87" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> private void handleLaunchActivity(ActivityClientRecord r Intent customIntent) { // If we are getting ready to gc after going to the background well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged = true; if (r.profilerInfo != null) { mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); } // Make sure we are running with the most recent config. handleConfigurationChanged(null null); if (localLOGV) Slog.v( TAG "Handling launch of " r); // Initialize before creating the activity WindowManagerGlobal.initialize(); //一个 perform开头的方法,启动Activity Activity a = performLaunchActivity(r customIntent); if (a != null) { r.createdConfig = new Configuration(mConfiguration); Bundle oldState = r.state; //Launch handleResumeActivity(r.token false r.isForward !r.activity.mFinished && !r.startsNotResumed); if (!r.activity.mFinished && r.startsNotResumed) { try { r.activity.mCalled = false; mInstrumentation.callActivityOnPause(r.activity); if (r.isPreHoneycomb()) { r.state = oldState; } if (!r.activity.mCalled) { throw new SuperNotCalledException( "Activity " r.intent.getComponent().toShortString() " did not call through to super.onPause()"); } } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { ..... } r.paused = true; } ..... } }</pre>

这个方法会将Activity创建出来

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n89" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> private Activity performLaunchActivity(ActivityClientRecord r Intent customIntent) { ActivityInfo aInfo = r.activityInfo; r.activityInfo.targetActivity); ...... Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl component.getClassName() r.intent); ....... } catch (Exception e) { ....... } Application app = r.packageInfo.makeApplication(false mInstrumentation); if (localLOGV) Slog.v(TAG "Performing launch of " r); if (activity != null) { 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); ....... //Activity的create方法执行 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的start方法执行 activity.performStart(); r.stopped = false; } mActivities.put(r.token r); return activity; }</pre>

反射创建Activity,为啥要用反射呢,此处搞不清楚

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n91" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public Activity newActivity(ClassLoader cl String className Intent intent) throws InstantiationException IllegalAccessException ClassNotFoundException { return (Activity)cl.loadClass(className).newInstance(); } </pre>

解析来mInstrumentation调用callActivityOnCreate方法

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n93" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public void callActivityOnCreate(Activity activity Bundle icicle PersistableBundle persistentState) { prePerformCreate(activity); activity.performCreate(icicle persistentState); postPerformCreate(activity); }</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n94" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> final void performCreate(Bundle icicle) { onCreate(icicle); mActivityTransitionState.readState(icicle); performCreateCommon(); }</pre>

onCreate方法在此处被调用了。

4.2、Activity的onStart是怎么回调的

在performLaunchActivity中调用了callActivityOnCreate之后,又会调用 activity.performStart()

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n98" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> final void performStart() { mActivityTransitionState.setEnterActivityOptions(this getActivityOptions()); mFragments.noteStateNotSaved(); mCalled = false; mFragments.execPendingActions(); mInstrumentation.callActivityOnStart(this); if (!mCalled) { throw new SuperNotCalledException( "Activity " mComponent.toShortString() " did not call through to super.onStart()"); } mFragments.dispatchStart(); mFragments.reportLoaderStart(); mActivityTransitionState.enterReady(this); }</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n99" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public void callActivityOnStart(Activity activity) { activity.onStart(); }</pre>

到此处start方法又被调用了。

4.3、Activity的onResume是怎么回调的

handleLaunchActivity方法中,在调用performLaunchActivity之后,调用了handleResumeActivity方法。

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n103" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">ActivityThread.handleResumeActivity() ActivityThread.handleResumeActivity() Activity.performResume() Instrumentation.callActivityOnResume();</pre>

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n104" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248 248 248); position: relative !important; border: 1px solid rgb(231 234 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51 51 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public void callActivityOnResume(Activity activity) { activity.mResumed = true; activity.onResume(); if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); for (int i=0; i<N; i ) { final ActivityMonitor am = mActivityMonitors.get(i); am.match(activity activity activity.getIntent()); } } } }</pre>

到此Activity的onResume方法被调用,onPause方法已经讲解过,关于onStop,onDestory一样的套路分析。

五、总结

关于Activity的启动过程分析,三篇文章都分析完了

  • 启动一个Activity的方式有多种,都是通过向Ams发送startActivity请求
  • Ams在启动Activity的时候,会判断目标进程有没有被创建,没有创建的话,向zygote进程发送创建进程的请求;
  • Zygote进程fork出新的子进程,即App进程;
  • App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
  • AMS所在的SystemServer进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
  • App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
  • 主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。
  • 说明了一个Activity的启动流程, 重点在于把握Binder的通信原理,接着弄清楚APP进程,SystemServer进程,Zygote进程是怎么互相通信的

好了,文章基本上就到这里,Activity启动详细流程的分析就到此完毕了!,如有地方不对或者有不同理解的可以提出来

有需要文中完整代码的同学 可以 私信发送 “底层源码” 即可 免费获取

现在私信还可以获得 更多《Android 学习笔记+源码解析+面试视频》

最后我想说:

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉

猜您喜欢: