首页系统综合问题Android常用组件—Activity启动详细流程

Android常用组件—Activity启动详细流程

时间2022-12-10 17:01:48发布分享专员分类系统综合问题浏览217

今天小编给各位分享bootingwindows的知识,文中也会对其通过Android常用组件—Activity启动详细流程和Activity启动流程笔记等多篇文章进行知识讲解,如果文章内容对您有帮助,别忘了关注本站,现在进入正文!

内容导航:

  • Android常用组件—Activity启动详细流程
  • Activity启动流程笔记
  • Activity的启动流程
  • 全面解析Activity: Activity的工作过程
  • 一、Android常用组件—Activity启动详细流程

    一、Activity请求启动

    我们以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 架构师之路还很漫长,与君共勉

    一、Activity启动流程笔记

    普通Activity的启动就是通过调用startActivity方法启动一个新的Activity,总体流程如下图:

    其中涉及到了两个进程,一个是App进程和AMS进程。整体的步骤是:
    1.启动者Activity向Instrumentation请求启动目标的Activity。
    2. Instrumentation通过AMS在App进程的IBinder接口(IActivityManager)访问AMS,此时App进程会阻塞等待AMS的调用返回,采用的跨进程通信技术是AIDL。
    3.AMS会进行一系列的验证工作,如判断目标Activity实例是否存在、启动模式是什么、有没有在AndroidManifest中注册等等。
    4.当AMS验证结束后会通过ClinentLifeCycleManager发送事物给App进程,利用App进程在AMS进程的IBinder接口(IApplicationThread)访问App进程ApplicationThread,采用的跨进程通信方式是AIDL。
    5.ApplicationThread是ActivityThread的内部类,当ApplicationThread接受到来自AMS的事务后,会将事务直接转交给ActivityThread处理。
    6.ActivityThread通过Instrumentation利用类加载器(反射)进行实例的创建,同时利用Instrumentation回调目标Activity的生命周期。
    介绍几个关键的类:

    Instrumentation:Instrumentation 是 Activity 与外界联系的类(不是 Activity 本身的类都统称为外界)。目标 Activity 通过 Instrumentation 来请求启动,ActivityThread 通过 Instrumentation 来创建 Activity 和回调 Activity 的生命周期。
    ActivityThread:每个应用程序只有一个唯一实例,负责对 Activity 创建的管理。ActivityThread 的内部类 ApplicationThread 只负责 App 进程和 AMS 进程的通信,将来自 AMS 的事务交给 ActivityThread 处理。
    AMS,全称 ActivityManagerService,系统级服务,负责管理四大组件。

    根Actvity就是我们点击手机桌面图标时,应用程序启动的第一个Activity。启动根Activity的流程其实和启动普通Activity的流程类似,只是启动根Activity时需要新建一个App进程。总体流程如下图:

    其中涉及到四个进程分别是:Launcher进程、AMS进程、App进程、Zygote进程。
    1.点击桌面图标后,Launcher进程访问AMS进程请求启动目标Activity,采用的跨进程方式是AIDL。
    2 AMS进程访问Zygote进程请求启动一个新的进程。采用的跨进程方式是Socket。
    3 Zygote进程通过调用fork函数创建一个App进程。
    4 App进程创建完成后,App进程访问AMS进程进行通知,采用的跨进程方式是AIDL。
    5 AMS进程收到来自App进程的通知后,将启动Activity的操作封装成事务,并将封装好的事务发送给App进程。
    6 App进程接受到来自AMS进程的事务后,根据事务创建目标Activity,并回调目标Activity的生命周期。

    本文主要是用来记录自己的学习笔记,看原文请移步: Activity 启动流程

    二、Activity的启动流程

    公众号

    面试官:说说 startActivity 吧

    🤔️:startActivity 主要就是应用进程与 system_server 进程的 AMS 通信,AMS 是实际来管理 Activity 组件的,负责处理启动模式,维护 Activity 栈等工作。startActivity 的大概流程就是由应用进程 IPC 调用到 AMS,AMS 处理完这些工作后再 IPC 回到应用进程,创建 Activity 的实例,回调 Activity 的生命周期。

    面试官:通过什么实现跨进程的呢?

    🤔️:都是通过 AIDL 接口,App 进程到 systemserver 进程是通过 IActivityServerManager.aidl ,systemserver 到 App 进程通过 IApplicationThread.aidl

    面试官:startActivity 时前后 Activity 的生命周期是怎样的?

    🤔️:旧 Activity 的 onPause 会先执行,然后新 Activity 依次执行 onCreate、onStart、onResume,随后再执行旧 Activity 的 onStop...

    面试官:旧 Activity 的 onPause 一定会先执行吗,为什么?

    🤔️:这主要是 AMS 来控制的,它会先后将前一个 Activity 的 onPause 事务和新 Activity 的启动事务发送给 App 进程,而在 App 端由 IApplicationThread.aidl 接受到后,会入队到 ActivityThread.H 的消息队列中,这个也是主线程消息队列,在队列上自然就实现了先后顺序的控制

    面试官:了解插件化吗,知道怎么启动一个插件中的 Activity 吗?

    🤔️:主要需要解决的问题是 Activity 未在 manifest 中注册的问题,因为在 AMS 中会检查 Activity 是否注册,而这个检查逻辑处于 systemserver 进程,我们是无法 hook 的,可以在 manifest 中提前注册一个占位 Activity,然后 startActivity 时进入到 systemserver 进程之前,hook 把未注册的 Activity 改为占位 Activity,AMS 检测就可以通过,然后再回到 App 进程后,把这个占位 Activity 再换成插件 Activity

    1.从本质来看,它不是一个线程,而是一个Java类;
    2.需要在主线程的方法中被运行;
    3.运行时,首先调用main方法,其中也会调用:OnAttatch,loop方法;
    4.AMS--->ActivityManagerService;
    5.ActivityManagerService;
    5.一个线程中,只有一个Looper对象;

    ActivityInfo 也是对Activity信息的描述,如主题,权限,启动方式,任务栈等

    – ActivityRecord:可以从它的类命名知道,这个记录Activity信息的类,主要记录一个Activity的所有信息。一个ActivityRecord只能对应一个Activity,但是一个Activity在系统中可以存在多份实例,所以一个Activity可以对应多个ActivityRecord记录
    – TaskRecord:TaskRecord由一个或者多个ActivityRecord组成,TaskRecord就是常说的任务栈,用来记录一个task里面的调用Activity的相关信息
    – ActivityStack:是用来管理TaskRecord的,一个ActivityStack会包含多个TaskRecord

    1、Application的创建。
    2、生命周期的管理。
    3、启动Activity。

    ActivityManagerNative是远程代理对象。通过ActivityManagerNative来操纵ActivityManagerService进行通信。客户端需要和ActivityManagerService进行通信,但是它们在不同的进程中,需要进行跨进程间进行通信,底层是用Binder实现。

    H类(Handler类的子类)会处理大量的ActivityManagerServer跨进程发送过来的消息,如启动Activity,暂停Activity等等

    Activity的attach方法实现了与Window对象的关联

    Activity中的Context对象向外关联了Activity本身

    ContextImpl appContext = ContextImpl.createActivityContext(this,r.packageInfo,r.token);

    appContext.setOuterContext(activity);

    Activity中的Context对象是每个Activity中自己的ContextImpl 类的实例对象,与Application中的Context不是同一个对象

    Application 对象创建完成后会通过mInstrumentation调用自己的onCreate生命周期方法

    window 给自己这只WindowManager对象

    WindowManager 对象通过(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)获得

    DecorView 继承自FrameLayout的View

    Activity的attach方法源码解读

    将Context对象attachBaseContext(context);

    setContentView方法源码解析

    调用PhoneWindow的setContectView

    getWindow().setContentView

    instrumentation.callApplicationOnCreate(app);

    'app.oncreate()'

    Application的真实创建过程

    通过反射创建并将ContextImpl attach给自己

    Application app = (Application) clazz.newInstance();

    app.attach(context);

    ContextImpl对象的创建时在makeApplication方法中创建的

    通过ActivityThread中的Instrumentation的newApplication方法创建

    Application对象并关联了ContextImpl对象

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

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

    Application 的创建位置

    Application app = r.packageInfo.makeApplication(false,mInstrumentation)

    Activity的创建

    通过类加载器加载完整的Activity类名反射创建Activity的类实例

    cl.loadClass(className).newInstance();

    Activity的创建机制是通过Java的反射机制创建的

    handleLaunchActivity调用performLaunchActivity方法创建Activity对象

    ActivityThread中的handleLaunchActivity方法中就启动、创建第一个Activity的

    在Activity的performCreate中调用自己的onCreate方法

    mH当中的handleResumeActivity方法处理ActivityManagerService返送的消息

    Activity的performResume()方法通过mInstrumentation.callActivityOnResume(this)方法调用到Activity的onResume()方法

    WindowManager 接口,继承与ViewManager接口

    调用Activity的onResume方法后View并没有立即被显示在屏幕上

    而是执行到mWindow.addView(decor)时

    WindowManagerImpl是WindowManager的真实实现类

    WindowManagerGlobal 类是具体实现对Window的管理

    WindowManagerGlobal中创建了ViewRootImpl 对象root

    ViewRootImpl是管理每一View的,是负责与远程的ActivityManagerServer进行交互的

    ViewRootImpl 对象的创建

    root = ViewRootImpl(view.getContext(), display);

    W extends IWindow.Stub

    W的对象实现了与远程ActivityManagerServer的交互

    ViewRootImpl 的setView方法实现与要显示的View进行关联

    每个View都有一个Parent,此Parent就是ViewRootImpl,ViewRootImpl负责View的绘制

    当Activity的onResume 执行后,程序继续向后执行直到执行了Activity的makeVisible()时View才真正的显示到了屏幕上

    mDecor.setVisibility(View.VISIBLE);

    通过ActivityManagerNative.getDefault().activityResumed(token);

    通知远程的ActivityManagerServer当前Activity为可见状态

    destory实际并没有直接销毁掉activity (8.1源码)

    通过performDestroyActivity()执行相应的生命周期方法performPauseActivityIfNeeded()、callActivityOnStop()、callActivityOnDestroy和移除它的IBinder

    通过WindowManager的实现类WindowManagerImpl调用removeViewImmediate(),拿到activity的实际控制类ViewRootImpl对象将他的父窗口(父布局)的指定分派为null

    将activity的content清理

    三、全面解析Activity: Activity的工作过程

    本文将对Activity的工作过程进行分析。

    主要学习以下内容:

    (1)系统内部是如何启动一个Activity的?

    (2)新Activity的对象是何时创建的?

    (3)Activity的各个生命周日是被系统何时回调的?

    Activity启动流程分两种,一种是启动正在运行的app的Activity,即启动子Activity。如无特殊声明默认和启动该activity的activity处于同一进程。如果有声明在一个新的进程中,则处于两个进程。另一种是打开新的app,即为Launcher启动新的Activity。后边启动Activity的流程是一样的,区别是前边判断进程是否存在的那部分。

    Activity的启动流程整体如下:

    一.Activity启动阶段

    (一)涉及到的概念

    进程:Android系统为每个APP分配至少一个进程

    IPC:跨进程通信,Android中采用Binder机制。

    (二)涉及到的类

    ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。

    ActivitySupervisor:管理 activity 任务栈

    ActivityThread:ActivityThread 运行在UI线程(主线程),App的真正入口。

    ApplicationThread:用来实现AMS和ActivityThread之间的交互。

    ApplicationThreadProxy:ApplicationThread 在服务端的代理。AMS就是通过该代理与ActivityThread进行通信的。

    IActivityManager:继承与IInterface接口,抽象出跨进程通信需要实现的功能

    AMN:运行在server端(SystemServer进程)。实现了Binder类,具体功能由子类AMS实现。

    AMS:AMN的子类,负责管理四大组件和进程,包括生命周期和状态切换。AMS因为要和ui交互,所以极其复杂,涉及window。

    AMP:AMS的client端代理(app进程)。了解Binder知识可以比较容易理解server端的stub和client端的proxy。AMP和AMS通过Binder通信。

    Instrumentation:仪表盘,负责调用Activity和Application生命周期。测试用到这个类比较多。

    (三)涉及到的进程

    (1)Launcher所在的进程

    (2)AMS所在的SystemServer进程

    (3)要启动的Activity所在的app进程

    如果是启动根Activity,就涉及上述三个进程。

    如果是启动子Activity,那么就只涉及AMS进程和app所在进程。

    (四)具体流程

    Launcher:Launcher通知AMS要启动activity。

    startActivitySafely->startActivity->Instrumentation.execStartActivity()(AMP.startActivity)->AMS.startActivity

    AMS:PMS的resoveIntent验证要启动activity是否匹配。如果匹配,通过ApplicationThread发消息给Launcher所在的主线程,暂停当前Activity(即Launcher)。

    暂停完,在该activity还不可见时,通知AMS,根据要启动的Activity配置ActivityStack。然后判断要启动的Activity进程是否存在?

    存在:发送消息LAUNCH_ACTIVITY给需要启动的Activity主线程,执行handleLaunchActivity

    不存在:通过socket向zygote请求创建进程。进程启动后,ActivityThread.attach

    判断Application是否存在,若不存在,通过LoadApk.makeApplication创建一个。在主线程中通过thread.attach方法来关联ApplicationThread。

    在通过ActivityStackSupervisor来获取当前需要显示的ActivityStack。

    继续通过ApplicationThread来发送消息给主线程的Handler来启动Activity (handleLaunchActivity)。

    handleLauchActivity:调用了performLauchActivity,里边Instrumentation生成了新的activity对象,继续调用activity生命周期。

    IPC过程:

    双方都是通过对方的代理对象来进行通信。

    1.app和AMS通信:app通过本进程的AMP和AMS进行Binder通信

    2.AMS和新app通信:通过ApplicationThreadProxy来通信,并不直接和ActivityThread通信

    (五)参考函数流程

    Activity启动流程(从Launcher开始):

    第一阶段: Launcher通知AMS要启动新的Activity(在Launcher所在的进程执行)

    第二阶段:AMS先校验一下Activity的正确性,如果正确的话,会暂存一下Activity的信息。然后,AMS会通知Launcher程序pause Activity(在AMS所在进程执行)

    第三阶段:pause Launcher的Activity,并通知AMS已经paused(在Launcher所在进程执行)

    第四阶段:检查activity所在进程是否存在,如果存在,就直接通知这个进程,在该进程中启动Activity;不存在的话,会调用Process.start创建一个新进程(执行在AMS进程)

    第五阶段: 创建ActivityThread实例,执行一些初始化操作,并绑定Application。如果Application不存在,会调用LoadedApk.makeApplication创建一个新的Application对象。之后进入Loop循环。(执行在新创建的app进程)

    第六阶段:处理新的应用进程发出的创建进程完成的通信请求,并通知新应用程序进程启动目标Activity组件(执行在AMS进程)

    第七阶段: 加载MainActivity类,调用onCreate声明周期方法(执行在新启动的app进程)

    从另一个角度下图来概括:

    下面简要介绍一下启动的过程:

            Step 1. 无论是通过Launcher来启动Activity,还是通过Activity内部调用startActivity接口来启动新的Activity,都通过Binder进程间通信进入到ActivityManagerService进程中,并且调用ActivityManagerService.startActivity接口; 

            Step 2. ActivityManagerService调用ActivityStack.startActivityMayWait来做准备要启动的Activity的相关信息;

            Step 3. ActivityStack通知ApplicationThread要进行Activity启动调度了,这里的ApplicationThread代表的是调用ActivityManagerService.startActivity接口的进程,对于通过点击应用程序图标的情景来说,这个进程就是Launcher了,而对于通过在Activity内部调用startActivity的情景来说,这个进程就是这个Activity所在的进程了;

            Step 4. ApplicationThread不执行真正的启动操作,它通过调用ActivityManagerService.activityPaused接口进入到ActivityManagerService进程中,看看是否需要创建新的进程来启动Activity;

            Step 5. 对于通过点击应用程序图标来启动Activity的情景来说,ActivityManagerService在这一步中,会调用startProcessLocked来创建一个新的进程,而对于通过在Activity内部调用startActivity来启动新的Activity来说,这一步是不需要执行的,因为新的Activity就在原来的Activity所在的进程中进行启动;

            Step 6. ActivityManagerServic调用ApplicationThread.scheduleLaunchActivity接口,通知相应的进程执行启动Activity的操作;

            Step 7. ApplicationThread把这个启动Activity的操作转发给ActivityThread,ActivityThread通过ClassLoader导入相应的Activity类,然后把它启动起来。

    关于bootingwindows的问题,通过《Activity的启动流程》、《全面解析Activity: Activity的工作过程》等文章的解答希望已经帮助到您了!如您想了解更多关于bootingwindows的相关信息,请到本站进行查找!

    爱资源吧版权声明:以上文中内容来自网络,如有侵权请联系删除,谢谢。

    bootingwindows
    win11系统在线安装教程Windows11系统在线重装 那些年周杰伦代言过的品牌,曾都瞬间崛起,如今却即将倒闭消失