Android中级——Activity数据恢复过程

Activity数据恢复

  • onSaveInstanceState()
  • onRestoreInstanceState()
  • 扩展

onSaveInstanceState()

在Activity调用onStop()之前调用会onSaveInstanceState(),如下

final void performStopActivity(IBinder token, boolean saveState, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    performStopActivityInner(r, null /* stopInfo */, saveState, false /* finalStateRequest */,
            reason);
}

private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean saveState, boolean finalStateRequest, String reason) {
	......
    callActivityOnStop(r, saveState, reason);
    ......
}

private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {
   	......
    final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null && !r.isPreHoneycomb();
    final boolean isPreP = r.isPreP();
    if (shouldSaveState && isPreP) {
        callActivityOnSaveInstanceState(r);
    }

    try {
        r.activity.performStop(r.mPreserveWindow, reason);
    }......
}

onSaveInstanceState()存储Window视图树、调用Fragment、ActivityLifecycleCallbacks的onSaveInstanceState()

protected void onSaveInstanceState(@NonNull Bundle outState) {
    outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
    outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
    Parcelable p = mFragments.saveAllState();
    if (p != null) {
        outState.putParcelable(FRAGMENTS_TAG, p);
    }
    if (mAutoFillResetNeeded) {
        outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
        getAutofillManager().onSaveInstanceState(outState);
    }
    dispatchActivitySaveInstanceState(outState);
}

上面调用到PhoneWindow的saveHierarchyState()

@Override
public Bundle saveHierarchyState() {
    Bundle outState = new Bundle();
    if (mContentParent == null) {
        return outState;
    }

    SparseArray states = new SparseArray();
    mContentParent.saveHierarchyState(states);	
    outState.putSparseParcelableArray(VIEWS_TAG, states);	//存储视图树的结构

    final View focusedView = mContentParent.findFocus();
    if (focusedView != null && focusedView.getId() != View.NO_ID) {
        outState.putInt(FOCUSED_ID_TAG, focusedView.getId());	//存储当前焦点所在View的ID,持有焦点的View必须设置ID,否则无法恢复
    }

    SparseArray panelStates = new SparseArray();
    savePanelState(panelStates);
    if (panelStates.size() > 0) {
        outState.putSparseParcelableArray(PANELS_TAG, panelStates);	//存储面板信息
    }

    if (mDecorContentParent != null) {
        SparseArray actionBarStates = new SparseArray();
        mDecorContentParent.saveToolbarHierarchyState(actionBarStates);
        outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);	//存储actionBar
    }

    return outState;
}

mContentParent即是Activity中setContentView()所设置的根布局,调用到View的saveHierarchyState()方法

public void saveHierarchyState(SparseArray container) {
    dispatchSaveInstanceState(container);
}

若当前是ViewGroup,则遍历child调用其dispatchSaveInstanceState()

@Override
protected void dispatchSaveInstanceState(SparseArray container) {
    super.dispatchSaveInstanceState(container);
    final int count = mChildrenCount;
    final View[] children = mChildren;
    for (int i = 0; i < count; i++) {
        View c = children[i];
        if ((c.mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED) {
            c.dispatchSaveInstanceState(container);
        }
    }
}

若当前是View,则从onSaveInstanceState()获取state根据当前View的ID保存到SparseArray

protected void dispatchSaveInstanceState(SparseArray container) {
    if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
        mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
        Parcelable state = onSaveInstanceState();
        ......
        if (state != null) {
            ......
            container.put(mID, state);
        }
    }
}

onSaveInstanceState()需要由子类自身去实现,以TextView为例,保存了字符串、间距、位置信息等

@Override
public Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();

    final boolean freezesText = getFreezesText();
    boolean hasSelection = false;
    int start = -1;
    int end = -1;
    if (mText != null) {
        start = getSelectionStart();
        end = getSelectionEnd();
        if (start >= 0 || end >= 0) {
            hasSelection = true;
        }
    }
    if (freezesText || hasSelection) {
        SavedState ss = new SavedState(superState);
        if (freezesText) {
            if (mText instanceof Spanned) {
                final Spannable sp = new SpannableStringBuilder(mText);
                if (mEditor != null) {
                    removeMisspelledSpans(sp);
                    sp.removeSpan(mEditor.mSuggestionRangeSpan);
                }
                ss.text = sp;
            } else {
                ss.text = mText.toString();
            }
        }
        if (hasSelection) {
            ss.selStart = start;
            ss.selEnd = end;
        }
        if (isFocused() && start >= 0 && end >= 0) {
            ss.frozenWithFocus = true;
        }
        ss.error = getError();
        if (mEditor != null) {
            ss.editorState = mEditor.saveInstanceState();
        }
        return ss;
    }
    return superState;
}

onRestoreInstanceState()

在performLaunchActivity()中,取出ActivityClientRecord中的state传给Activity的OnCreate()方法,在正常启动时,state为空,需要对state进行判空

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    try {
        	......
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
             ......
            r.activity = activity;
        } 
		......
		synchronized (mResourcesManager) {
    		mActivities.put(r.token, r);
		}
    }......

    return activity;
}

在handleStartActivity()中先调用onStart(),再调用OnRestoreInstanceState()

@Override
public void handleStartActivity(IBinder token, PendingTransactionActions pendingActions) {
    final ActivityClientRecord r = mActivities.get(token);
    final Activity activity = r.activity;
 	......
    activity.performStart("handleStartActivity");
    ......
    if (pendingActions.shouldRestoreInstanceState()) {
        if (r.isPersistable()) {
            if (r.state != null || r.persistentState != null) {
                mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                        r.persistentState);
            }
        } else if (r.state != null) {
            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
        }
    }
    ......
}

扩展

Activity并非每次退出都会调用onSaveInstanceState(),如当用户按Back键主动退出时,下面列举几种调用onSaveInstanceState()的情况

  • 按下Home键
  • 长按Home键选中运行其他程序
  • 按下电源键息屏
  • 从Activity启动一个新的Activity
  • 屏幕方向切换
  • 电话打入

你可能感兴趣的:(#,Android中级,android,java,开发语言,备忘录模式)