Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android源碼解析(二十四)--)onSaveInstanceState執行時機

android源碼解析(二十四)--)onSaveInstanceState執行時機

編輯:關於Android編程

我們已經分析過Activity的啟動流程,從中也分析了Activity的生命周期。而其中有一個生命周期方法:onSaveInstanceState方法,今天我們主要講解一下onSaveInstanceState方法的執行時機。
可能部分同學對Activity的onSaveInstanceState方法不是特別熟悉,這裡我們簡單介紹一下。onSaveInstanceState方法是Activity的成員方法,主要用於在Activity銷毀時保存Activity相關的對象信息,而其執行的時機不是我們主動調用的,而是Android系統的framework幫忙調用的,而其調用的時機,可以參考android系統的介紹:

This method is called before an activity may be killed so that when it comes back some time in the future it can restore its state. For example, if activity B is launched in front of activity A, and at some point activity A is killed to reclaim resources, activity A will have a chance to save the current state of its user interface via this method so that when the user returns to activity A, the state of the user interface can be restored via {@link #onCreate} or {@link #onRestoreInstanceState}.

可以發現onSaveInstanceState方法會在Activity將要被kill的時候執行。O(∩_∩)O哈哈~,可能跟以前講解的內容不是太對,我們看過不少文章都是說onSaveInstanceStatex方法會在Activity容易被銷毀的時候執行。那麼這裡明明說的是當Activity被銷毀的時候就會執行onSaveInstanceState方法,那麼具體的情況是如何的呢?我們具體看一下源碼吧,哈哈。

通過分析Activity的生命周期方法,我們知道onSaveInstanceState方法在onPause方法之後執行在onStop方法之前執行。這裡我們首先看一下onPause方法的源碼邏輯。

Activity在執行onPause方法的時候回回調ActivityThread的handlePauseActivity方法。

好吧,先具體看一下ActivityThread.handlePauseActivity的源碼:

private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(token, finished, r.isPreHoneycomb());

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }

            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

在方法體中我們除了執行一些其他的操作,然後在handlePauseActivity方法體中調用了performPauseActivity方法,這個方法就是具體執行回調pauseActivity操作的方法,既然這樣我們在看一下performPauseActivity方法的實現:

final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState) {
        ActivityClientRecord r = mActivities.get(token);
        return r != null ? performPauseActivity(r, finished, saveState) : null;
    }

可以發現在performPauseActivity方法中首先判斷ActivityClientRecord是否為空,然後又調用了performPauseActivity方法的重載方法:

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {
        ...
        if (!r.activity.mFinished && saveState) {
            callCallActivityOnSaveInstanceState(r);
        }
        ...
    }

可以發現,這裡調用了callCallActivityOnSaveInstanceState方法,看名稱可以發現這裡應該回調的是Activity的onSaveInstanceState方法,但是這裡執行之前有一個條件判斷,首先會判斷這裡的Activity是否被finish?應為這時候剛剛執行onPause方法所以這裡的mFinished變量為false,所以判斷執行callCallActivityOnSaveInstanceState方法只要需要通過saveState變量來判斷了,而這裡的saveState方法是performPauseActivity方法傳遞過來的。。。。好吧,我們來看一下調用performPauseActivity方法時saveState變量是如何賦值的。回到我們的handlePauseActivity方法,看一下performPauseActivity方法是如何調用的:

performPauseActivity(token, finished, r.isPreHoneycomb());

可以發現saveState boolean變量是通過r.isPreHoneycomb方法賦值的,這裡我們看一下IsPreHoneycomb方法是如何實現的:

public boolean isPreHoneycomb() {
            if (activity != null) {
                return activity.getApplicationInfo().targetSdkVersion
                        < android.os.Build.VERSION_CODES.HONEYCOMB;
            }
            return false;
        }

可以發現當我們的App設置的targetSdk版本號小於android versionCode 11也就是android3.0的時候返回為true,其他的時候返回為false,也就是說當我們App設置的targetVersion大於android3.0的時候才會執行callCallActivityOnSaveInstanceState方法,好吧,繼續看一下callCallActivityOnSaveInstanceState方法是如何實現的:

private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
        r.state = new Bundle();
        r.state.setAllowFds(false);
        if (r.isPersistable()) {
            r.persistentState = new PersistableBundle();
            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
                    r.persistentState);
        } else {
            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
        }
    }

可以發現方法體主要調用了mInstrumentation的callActivityOnSaveInstanceState方法,既然這樣,我們再來看一下callActivityOnSaveInstanceState方法:

public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
            PersistableBundle outPersistentState) {
        activity.performSaveInstanceState(outState, outPersistentState);
    }

這裡方法體中又回調了Activity的performSaveInstanceState方法。。。

final void performSaveInstanceState(Bundle outState) {
        onSaveInstanceState(outState);
        saveManagedDialogs(outState);
        mActivityTransitionState.saveState(outState);
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
    }

可以看到這裡回調了Activity的onSaveInstanceState方法,這樣經過一系列的方法回調之後我們就執行了onSaveInstanceState方法。

這樣我們當只執行onPause方法的時候一般通過設置targetVersion控制是否執行onSaveInstanceState方法,當設置的targetVersionCode大於android3.0的時候默認不會執行onSaveInstanceState方法。

然後我們看一下當Activity執行onStop方法的時候是否會執行onSaveInstanceState方法,通過之前分析的Activity的啟動流程,我們知道Actvitiy執行onStop方法會回調ActivityThread的handleStopActivity,這樣我們先看一下handleStopActivity方法的實現:

private void handleStopActivity(IBinder token, boolean show, int configChanges) {
        ActivityClientRecord r = mActivities.get(token);
        r.activity.mConfigChangeFlags |= configChanges;

        StopInfo info = new StopInfo();
        performStopActivityInner(r, info, show, true);

        if (localLOGV) Slog.v(
            TAG, "Finishing stop of " + r + ": show=" + show
            + " win=" + r.window);

        updateVisibility(r, show);

        info.activity = r;
        info.state = r.state;
        info.persistentState = r.persistentState;
        mH.post(info);
        mSomeActivitiesChanged = true;
    }

然後我們發現在方法performStopActivity方法中調用了performStopActivityInner方法,我們繼續看一下performStopActivityInner方法的實現:

private void performStopActivityInner(ActivityClientRecord r,
            StopInfo info, boolean keepShown, boolean saveState) {
        ...
            if (!r.activity.mFinished && saveState) {
                if (r.state == null) {
                    callCallActivityOnSaveInstanceState(r);
                }
            }
            ...
    }

可以發現還是通過saveState變量來控制是否調用onSaveInstanceState,而這裡的saveState變量是在performStopActivityInner方法調用的時候傳遞的,回到我們的handleStopActivity方法中關於performStopActivityInner調用的代碼:

performStopActivityInner(r, info, show, true);

好吧,這裡直接傳值為true,這樣我們執行Activity的stop方法一定執行onSaveInstanceState方法。

總結

onSaveInstanceState方法是Activity的生命周期方法,主要用於在Activity銷毀時保存一些信息。

當Activity只執行onPause方法時(Activity a打開一個透明Activity b)這時候如果App設置的targetVersion大於android3.0則不會執行onSaveInstanceState方法。

當Activity執行onStop方法時,通過分析源碼我們知道調用onSaveInstanceState的方法直接傳值為true,所以都會執行onSaveInstanceState方法。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved