Activity關閉源碼分析(三)

對於Activity的啓動可以觀看上一篇android啓動流程分析(二)進行查看下面分析activity的關閉流程如下圖:


看高清圖請下載

關閉activity的時候回調用finish方法代碼如下:

    public void finish() {
        finish(DONT_FINISH_TASK_WITH_ACTIVITY);
    }
   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 (ActivityManagerNative.getDefault()
                        .finishActivity(mToken, resultCode, resultData, finishTask)) {//調用ActivityManagerService
                    mFinished = true;
                }
            } catch (RemoteException e) {
                // Empty
            }
        } else {
            mParent.finishFromChild(this);
        }
    }
在這裏稍微解釋下mParent這個參數:Activity中存在父子Activity的關係。mParent參數是對那些在ActivityGroup中的Activity來說的。比如說在TabActivity中的Tab頁面裏嵌套的Activity,他們的mParent就是TabActivity。mParent的賦值在Activity.setParent(Activity parent)方法中定義。大多數Activity.mParent爲空,因此此處直接往AMS.finishActivity流程走。這裏我們只分析沒有父類的,以及上父類的關閉原理也差不多。

對於ActivityManagerNative.getDefault().finishActivity(mToken, resultCode, resultData, finishTask)這句話實際就是調用了Ams裏面的finishActivity方法(爲什麼可以查看前面的文章android啓動流程分析(一)),直接查看Ams中的方法代碼如下:

    public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
            int finishTask) {
        ......
            try {
                boolean res;
                final boolean finishWithRootActivity =
                        finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
                if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
                        || (finishWithRootActivity && r == rootR)) {
                    // If requested, remove the task that is associated to this activity only if it
                    // was the root activity in the task. The result code and data is ignored
                    // because we don't support returning them across task boundaries. Also, to
                    // keep backwards compatibility we remove the task from recents when finishing
                    // task with root activity.
                    res = removeTaskByIdLocked(tr.taskId, false, finishWithRootActivity);
                    if (!res) {
                        Slog.i(TAG, "Removing task failed to finish activity");
                    }
                } else {
                    res = tr.stack.requestFinishActivityLocked(token, resultCode,
                            resultData, "app-request", true);//關閉activity
                    if (!res) {
                        Slog.i(TAG, "Failed to finish by app-request");
                    }
                }
                return res;
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }
從上面的代碼可以看出這個關閉activity的語句調用的是ActivityStack類裏面的requestFinishActivityLocked方法,代碼如下:

    final boolean requestFinishActivityLocked(IBinder token, int resultCode,
            Intent resultData, String reason, boolean oomAdj) {
         ......
        finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
        return true;
    }
   final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
            String reason, boolean oomAdj) {
        ......
        if (mResumedActivity == r) {//當前activity關閉的時候調用

            ......

            if (mPausingActivity == null) {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
                if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                        "finish() => pause with userLeaving=false");
                startPausingLocked(false, false, false, false);
            }

            if (endTask) {
                mStackSupervisor.removeLockedTaskLocked(task);
            }
        } else if (r.state != ActivityState.PAUSING) {//不在暫停狀態的情況下調用
            ......
            return finishCurrentActivityLocked(r, (r.visible || r.nowVisible) ?
                    FINISH_AFTER_VISIBLE : FINISH_AFTER_PAUSE, oomAdj) == null;
        } else {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
        }

        return false;
    }
如上面的代碼有兩個分支,我們是調用的activity的finish因此我們走的是第一種,調用了startPausingLocked方法代碼如下:

  final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
            boolean dontWait) {
        .....
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            } catch (Exception e) {
                // Ignore exception, if process died other code will cleanup.
                Slog.w(TAG, "Exception thrown during pause", e);
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }
        } else {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }

       .........
    }
對於上面的prev.app.thread代表的是ActivityThread::ApplicationThread不明可以查看前面的文章(android啓動流程分析(一))schedulePauseActivity方法代碼如下:

        public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            int seq = getLifecycleSeq();
            if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
                    + " operation received seq: " + seq);
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                    configChanges,
                    seq);
        }
雖然上面的Message有兩種狀態但是最終調用的都是同一個方法代碼如下:

  private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
       ......
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

         .....
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
            mSomeActivitiesChanged = true;
        }
    }
   final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {
			......

        // Next have the activity save its current state and managed dialogs...
        if (!r.activity.mFinished && saveState) {
            callCallActivityOnSaveInstanceState(r);//調用activity的OnSaveInstanceState方法
        }

        performPauseActivityIfNeeded(r, reason);//調用activity的onpause方法

        ......
    }

根據上面的代碼可知activity在沒有調用關閉以及saveState爲true(有AMS控制的)時候會調用OnSaveInstanceState方法,接下來調用onPause方法,進一步分析performPauseActivityIfNeeded代碼如下:

	   private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
             ......
            mInstrumentation.callActivityOnPause(r.activity);
              ......
        r.paused = true;
    }
調用了Activity類中的下面方法,上面調用的是Instrumentation類中的方法
   final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        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;
    }
到這裏位置onPause方法就被調用了,接下來在ActivityThread這個類中的handlePauseActivity方法中來由一句話調用了代碼如下:

            // Tell the activity manager we have paused.通過這意思是activity進入paused狀態的時候調用
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
對於ActivityManagerNative.getDefault().activityPaused(token);這句話一看就知道最終調用的是AMS中的activityPaused方法,此方法代碼如下:

    @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);
    }

接下來調用了ActivityStack類中的activityPausedLocked方法,代碼如下

 private void completePauseLocked(boolean resumeNext) {
        ActivityRecord prev = mPausingActivity;
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);

        if (prev != null) {
            final boolean wasStopping = prev.state == ActivityState.STOPPING;
            prev.state = ActivityState.PAUSED;
            if (prev.finishing) {//這個一般不不會調用之後再內存不足的時候纔會調用
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
            } else if (prev.app != null) {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
                        + " wasStopping=" + wasStopping + " visible=" + prev.visible);
                if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) {
                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
                            "Complete pause, no longer waiting: " + prev);
                }
                if (prev.deferRelaunchUntilPaused) {
                    // Complete the deferred relaunch that was waiting for pause to complete.
                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
                    relaunchActivityLocked(prev, prev.configChangeFlags, false,
                            prev.preserveWindowOnDeferredRelaunch);
                } else if (wasStopping) {
                    // We are also stopping, the stop request must have gone soon after the pause.
                    // We can't clobber it, because the stop confirmation will not be handled.
                    // We don't need to schedule another stop, we only need to let it happen.
                    prev.state = ActivityState.STOPPING;
                } else if ((!prev.visible && !hasVisibleBehindActivity())
                        || mService.isSleepingOrShuttingDownLocked()) {
                    // If we were visible then resumeTopActivities will release resources before
                    // stopping.
                    addToStopping(prev, true /* immediate */);
                }
            } else {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
                prev = null;
            }
            // It is possible the activity was freezing the screen before it was paused.
            // In that case go ahead and remove the freeze this activity has on the screen
            // since it is no longer visible.
            prev.stopFreezingScreenLocked(true /*force*/);
            mPausingActivity = null;
        }

        if (resumeNext) {
		        ......
                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);//回覆前面的activy
				......
        }
		......
    }


在這裏調用resumeFocusedStackTopActivityLocked方法進行啓動上一個Activity代碼如下:

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        }
       
 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }
   private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
		......
        Bundle resumeAnimOptions = null;
        if (anim) {
            ActivityOptions opts = next.getOptionsForTargetActivityLocked();
            if (opts != null) {
                resumeAnimOptions = opts.toBundle();
            }
            next.applyOptionsLocked();
        } else {
            next.clearOptionsLocked();
        }

        ActivityStack lastStack = mStackSupervisor.getLastStack();
        if (next.app != null && next.app.thread != null) {
            ......
            try {
                // Deliver all pending results.
                ArrayList<ResultInfo> a = next.results;
                if (a != null) {
                    final int N = a.size();
                    if (!next.finishing && N > 0) {
                        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                                "Delivering results to " + next + ": " + a);
                        next.app.thread.scheduleSendResult(next.appToken, a);
                    }
                }

                if (next.newIntents != null) {
                    next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
                }

               ......
                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward(), resumeAnimOptions);

                mStackSupervisor.checkReadyForSleepLocked();
			  .....
    }

對於上面next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState, mService.isNextTransitionForward(), resumeAnimOptions);方法就是activity啓動的時候調用的一樣的可以參照上一篇文章(android啓動流程分析(二)),這裏面會調用onReStart-->onStart--->onResume生命週期我們在看看handleResumeActivity方法

 final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
		......

        // TODO Push resumeArgs into the activity for consideration
        r = performResumeActivity(token, clearHide, reason);

        ......




            if (!r.onlyLocalRequest) {
                r.nextIdle = mNewActivities;
                mNewActivities = r;
                if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r);
                Looper.myQueue().addIdleHandler(new Idler());
            }
        .....
    }
通過上面的方法我們能看到在運行完performResumeActivity方法之後會執行Looper.myQueue().addIdleHandler(new Idler());可以查看Idler的類

 private class Idler implements MessageQueue.IdleHandler {
        @Override
        public final boolean queueIdle() {
            ActivityClientRecord a = mNewActivities;
            boolean stopProfiling = false;
            if (mBoundApplication != null && mProfiler.profileFd != null
                    && mProfiler.autoStopProfiler) {
                stopProfiling = true;
            }
            if (a != null) {
                mNewActivities = null;
                IActivityManager am = ActivityManagerNative.getDefault();
                ActivityClientRecord prev;
                do {
                    if (localLOGV) Slog.v(
                        TAG, "Reporting idle of " + a +
                        " finished=" +
                        (a.activity != null && a.activity.mFinished));
                    if (a.activity != null && !a.activity.mFinished) {
                        try {
                            am.activityIdle(a.token, a.createdConfig, stopProfiling);
                            a.createdConfig = null;
                        } catch (RemoteException ex) {
                            throw ex.rethrowFromSystemServer();
                        }
                    }
                    prev = a;
                    a = a.nextIdle;
                    prev.nextIdle = null;
                } while (a != null);
            }
            if (stopProfiling) {
                mProfiler.stopProfiling();
            }
            ensureJitEnabled();
            return false;
        }
    }

內部有一個queueIdle的回調方法,當它被添加到MessageQueue之後就會回調該方法,我們可以發現在這個方法體中調用了ActivityManagerNative.getDefault.activityIdle方法,通過之前的我們知道ActivityManagerNative.getDefault方法最終調用的是AMs中的方法activityIdle查看代碼如下:

   @Override
    public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
       .....
                ActivityRecord r =
                        mStackSupervisor.activityIdleInternalLocked(token, false, config);//
       .....
    }

接下來調用下面方法ActivityStackSupervisor這個類中的方法

  final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
            Configuration config) {
		......
        for (int i = 0; i < NS; i++) {
            r = stops.get(i);
            final ActivityStack stack = r.task.stack;
            if (stack != null) {
                if (r.finishing) {
                    stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
                } else {
                    stack.stopActivityLocked(r);
                }
            }
        }
		......
    }

通過判斷語句可以知道如果要關閉就走第一條,否則就是進行stop狀態,查看一下finishCurrentActivityLocked方法如下(在ActivityStack中):

final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
        ......
            boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
			......
    }
  final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
        ......

            try {
                if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
                r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
                        r.configChangeFlags);
            } catch (Exception e) {
                // We can just ignore exceptions here...  if the process
                // has crashed, our death notification will clean things
                // up.
                //Slog.w(TAG, "Exception thrown during finish", e);
                if (r.finishing) {
                    removeActivityFromHistoryLocked(
                            r, topTask, reason + " exceptionInScheduleDestroy");
                    removedFromHistory = true;
                    skipDestroy = true;
                }
            }

           ......
    }
通過前面的分析r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,r.configChangeFlags);這就話實際上是調用了ActivityThread::ApplicationThread中的方法
  private void handleDestroyActivity(IBinder token, boolean finishing,
            int configChanges, boolean getNonConfigInstance) {
        ActivityClientRecord r = performDestroyActivity(token, finishing,
                configChanges, getNonConfigInstance);
        ......
        if (finishing) {
            try {
                ActivityManagerNative.getDefault().activityDestroyed(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
        mSomeActivitiesChanged = true;
    }
 private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
            int configChanges, boolean getNonConfigInstance) {
          ......
           r.activity.performStop(r.mPreserveWindow);

               r.activity.mCalled = false;
                mInstrumentation.callActivityOnDestroy(r.activity);
		......
    }
上面的方法在進一步分析就能知道剩下的聲明週期是onStop--->onDestory


總結:通過上一篇和這這一篇得出activity的啓動和關閉流程的生命週期的如下:

1、當啓動第一個Activity_A的時候的生命週期運行的方法:

 onCreate--->onStart--->onPostCreate--->onResume--->onPostResume

 這是鎖屏運行方法

 onPause--->onSaveInstanceState--->onStop

 開屏運行方法

 onRestart--->onStart--->onResume--->onPostResume

2、在Activity_A中打開Activity_B的生命週期運行的方法:

 A_onPause--->B_onCreate--->B_onStart--->B_onPostCreate--->B_onResume--->B_onPostResume--->A_onSaveInstanceState---->A_onStop

3、關閉Activity_B

 B_onPause--->A_onRestart--->A_onStart--->A_onResume--->A_onPostResume--->B_onStop---->B_onDestroy














發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章