1. 程式人生 > >Android進階3:Activity原始碼分析(2) —— Activity啟動和銷燬流程(8.0)

Android進階3:Activity原始碼分析(2) —— Activity啟動和銷燬流程(8.0)

上篇文章講述了app從啟動建立Activity呼叫onCreate,onStart, onResume方法,這篇文章講述一下Activity啟動的另一個切入點:startActivity方法,啟動Activity。

通過上一篇文章,我們總結一下: 1:ActivityThread是通過Instrumentation排程Activity的生命週期的 2:ApplicationThread繼承自IApplicationThread.Stub,本身就是一個Binder物件。AMS給ActivityThread傳遞資訊,就是通過Binder機制,也就是ApplicationThread傳遞的。 3:Instrumentation內部提供了建立Activity,呼叫Activity的方法,建立Application,呼叫Application的方法,至少從我們上一篇文章得到的結論是:Instrumentation好比一個管家,管理著Activity和Application的生命週期。

接下來是一些小知識點: 1:我們之前說的UI主執行緒初始化Looper是在ActivityThread中的main方法中,這就是為什麼我們可以在UI層直接傳送使用Handler機制。 2:專案開發中總是在Application的onCreate中,做一些初始化操作,因為Application的建立的比Activity建立更早,並且Application 的onCreate方法呼叫的更早。

好了,開始分析另一個切入點:Activity的startActivity(…)

Activity啟動:startActivity()

先看下Activity的startActivity原始碼:

    @Override
public void startActivity(Intent intent) { this.startActivity(intent, null); } //Bundle : 傳遞的資料 @Override public void startActivity(Intent intent, @Nullable Bundle options) { //不需要返回資料,requestCode預設:-1 if (options != null) { startActivityForResult(intent, -1
, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } } public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) { startActivityForResult(intent, requestCode, null); } public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { //requestCode = -1 options = transferSpringboardActivityOptions(options); //呼叫Instrumentation的execStartActivity方法; Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); ...... }

通過上述程式碼可以看到:startActivity其實最終呼叫的都是startActivityForResult,如果不需要返回值,requestCode傳遞-1, 此時呼叫Instrumentation的execStartActivity方法。

   public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {

        .....

        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            /*
            ActivityManager.getService().startActivity()就是IActivityManager的代理物件呼叫了startActivity方法,通過binder機制,
            從而呼叫ActivityManagerService的startActivity方法。
             */
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

再呼叫AMS的startActivity方法,Binder機制

        @Override
        public int startActivity(IBinder whoThread, String callingPackage,
                Intent intent, String resolvedType, Bundle bOptions) {
            .......
            return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
                    resolvedType, null, null, null, null, 0, 0, null, null,
                    null, bOptions, false, callingUser, null, tr, "AppTaskImpl");
        }

進入:startActivityMayWait


    final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask, String reason) {

            .......

            final ActivityRecord[] outRecord = new ActivityRecord[1];
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask, reason);
            ........

    }

進入:startActivityLocked


    int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask, String reason) {

        .........

        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                container, inTask);
        .........

    }

進入:startActivity


    /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {
        ........

        doPendingActivityLaunchesLocked(false);

        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                options, inTask, outActivity);
    }

進入:doPendingActivityLaunchesLocked


    final void doPendingActivityLaunchesLocked(boolean doResume) {
        while (!mPendingActivityLaunches.isEmpty()) {
            final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
            final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
            try {
                startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
                        null, null /*outRecords*/);
            } catch (Exception e) {
                Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
                pal.sendErrorResult(e.getMessage());
            }
        }
    }

進入:startActivity


    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        int result = START_CANCELED;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } 
        ......

    }

進入startActivityUnchecked

  // Note: This method should only be called from {@link startActivity}.
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {

        .......
        if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();
         }

         .......
    }

進入:resumeFocusedStackTopActivityLocked


    boolean resumeFocusedStackTopActivityLocked() {
        return resumeFocusedStackTopActivityLocked(null, null, null);
    }

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        .......

        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.state == RESUMED) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        return false;
    }

進入resumeTopActivityUncheckedLocked:

   boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        ........

        result = resumeTopActivityInnerLocked(prev, options);

        ......
    }

進入resumeTopActivityInnerLocked:

   private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {

        ......
        mStackSupervisor.startSpecificActivityLocked(next, true, true);

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }

進入startSpecificActivityLocked:


    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.getStack().setLaunchTime(r);

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

            ....

            realStartActivityLocked(r, app, andResume, checkConfig);

            ......

        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

進入:realStartActivityLocked


    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {

            .......

            /*
            通過binder機制,通過代理呼叫ApplicationThread的scheduleLaunchActivity方法。將啟動Activity的操作交給ApplicationThread類
             */
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    // TODO: Have this take the merged configuration instead of separate global and
                    // override configs.
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);

             ......


    }

app.thread也就是ApplicationThread,交給UI層處理,進入scheduleLaunchActivity:

       // we use token to identify this activity without having to send the
        // activity itself back to the activity manager. (matters more with ipc)
        @Override
        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);

            //用於封裝啟動Activity一些引數值
            ActivityClientRecord r = new ActivityClientRecord();

            ......
            sendMessage(H.LAUNCH_ACTIVITY, r);


        }

傳送訊息:


    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        .....

        //啟動Activity
        Activity a = performLaunchActivity(r, customIntent);

        .....
    }

接下來就跟上一篇文章分析走的流程一樣的:

performLaunchActivity ——》 Instrumentation & callActivityOnCreate ——》Activity & performCreate ——》Activity & onCreate

至此Activity就建立完畢了。通過上述流程分析,我們再一次大致瞭解了流程:

Activity通過Binder機制呼叫Instrumentation, Instrumentation在通過Binder機制呼叫AMS的方法,AMS經過一系列操作,然後再通過Binder機制返回給主執行緒的ApplicationThread, 此時傳送訊息交給ActivityThread處理,再通過Binder機制,讓Instrumentation統一處理Activity的生命週期,呼叫onCreate方法。

接下來再說一下finish的關閉流程吧

finish關閉Activity原始碼

呼叫finish方法最終都會呼叫以下方法:

   private void finish(int finishTask) {
        if (mParent == null) {
            int resultCode;
            Intent resultData;
            synchronized (this) {
                resultCode = mResultCode;
                resultData = mResultData;
            }
            if (false) Log.v(TAG, "Finishing self: token=" + mToken);
            try {
                if (resultData != null) {
                    resultData.prepareToLeaveProcess(this);
                }
                if (ActivityManager.getService()
                        .finishActivity(mToken, resultCode, resultData, finishTask)) {
                    mFinished = true;
                }
            } catch (RemoteException e) {
                // Empty
            }
        } else {
            mParent.finishFromChild(this);
        }
    }

呼叫AMS的finishActivity方法:

   @Override
    public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
            int finishTask) {

        .....
        res = tr.getStack().requestFinishActivityLocked(token, resultCode,
            resultData, "app-request", true);

       .......

    }

進入ActivityStack的requestFinishActivityLocked方法:

   /**
     * @return Returns true if the activity is being finished, false if for
     * some reason it is being left as-is.
     */
    final boolean requestFinishActivityLocked(IBinder token, int resultCode,
            Intent resultData, String reason, boolean oomAdj) {
        ActivityRecord r = isInStackLocked(token);
        if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES,
                "Finishing activity token=" + token + " r="
                + ", result=" + resultCode + ", data=" + resultData
                + ", reason=" + reason);
        if (r == null) {
            return false;
        }

        finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
        return true;
    }

進入:finishActivityLocked

    final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
            String reason, boolean oomAdj) {
        return finishActivityLocked(r, resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY);
    }

    /**
     * @return Returns true if this activity has been removed from the history
     * list, or false if it is still in the list and will be removed later.
     */
    final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
            String reason, boolean oomAdj, boolean pauseImmediately) {
        ......

        final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj)
                        == null;
        .......

    }

進入:finishCurrentActivityLocked


    final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
        .......

        boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");

        .......
    }

進入:destroyActivityLocked

   final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
        ........
        r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
                        r.configChangeFlags);
        ........

   }

進入ApplicationThread的scheduleDestroyActivity方法內,傳送訊息,進入到ActivityThread的handleDestroyActivity方法:

   private void handleDestroyActivity(IBinder token, boolean finishing,
            int configChanges, boolean getNonConfigInstance) {
        ActivityClientRecord r = performDestroyActivity(token, finishing,
                configChanges, getNonConfigInstance);
        ......
  }

進入performDestroyActivity方法:

    private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
            int configChanges, boolean getNonConfigInstance) {
        ActivityClientRecord r = mActivities.get(token);
        Class<? extends Activity> activityClass = null;
        if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
        if (r != null) {
            activityClass = r.activity.getClass();
            r.activity.mConfigChangeFlags |= configChanges;
            if (finishing) {
                r.activity.mFinished = true;
            }

            //步驟1:pause Activity
            performPauseActivityIfNeeded(r, "destroy");

            if (!r.stopped) {
                try {
                    //步驟2:stop Activity
                    r.activity.performStop(r.mPreserveWindow);
                } catch (SuperNotCalledException e) {
                    throw e;
                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to stop activity "
                                + safeToComponentShortString(r.intent)
                                + ": " + e.toString(), e);
                    }
                }
                r.stopped = true;
                EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
                        r.activity.getComponentName().getClassName(), "destroy");
            }
            if (getNonConfigInstance) {
                try {
                    r.lastNonConfigurationInstances
                            = r.activity.retainNonConfigurationInstances();
                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to retain activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
            }
            try {
                r.activity.mCalled = false;
                //步驟3:destroy Activity
                mInstrumentation.callActivityOnDestroy(r.activity);

            .......

      }

先看步驟1: 進入performPauseActivityIfNeeded:


    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        .......
        mInstrumentation.callActivityOnPause(r.activity);
        .......
    }

呼叫了Instrumentation的callActivityOnPause方法,方法內呼叫Activity的performPause方法,內部呼叫onPause方法, 所以finish Activity時,onPause最先觸發。

接下來看下步驟2:performStop:

   final void performStop(boolean preserveWindow) {
       .......
       mInstrumentation.callActivityOnStop(this);
       .......
   }

呼叫了Instrumentation的callActivityOnStop方法,然後方法內有呼叫了Activity的onStop方法。

接下來看步驟3:呼叫了Instrumentation的callActivityOnDestroy方法:

  public void callActivityOnDestroy(Activity activity) {
    activity.performDestroy();
  }

呼叫了Activity的performDestroy方法:


    final void performDestroy() {
        mDestroyed = true;
        mWindow.destroy();
        mFragments.dispatchDestroy();
        //我們最終想看到的方法
        onDestroy();
        mFragments.doLoaderDestroy();
        if (mVoiceInteractor != null) {
            mVoiceInteractor.detachActivity();
        }
    }

至此finish Activity的流程就算走完了 finish Activity的方法回撥是:onPause ——》onStop ——》onDestroy

AMS互動的大致流程就是:finish呼叫AMS的方法,經過一系列操作,然後返回給主執行緒的ApplicationThread處理,傳送訊息,交給ActivityThread處理,然後Activity的生命週期的方法,有Instrumentation統一管理排程。

上述分析如果有錯誤,感覺指正O(∩_∩)O!

Android學習交流:

這裡寫圖片描述