美文网首页
onSaveInstanceState与onRestoreIns

onSaveInstanceState与onRestoreIns

作者: 迷途之中小书童 | 来源:发表于2018-09-14 11:38 被阅读0次

    如果没有对activity配置做处理,那么onSaveInstanceState会在手机系统配置发生变化时进行调用,例如手机横竖屏切换,用于保存当前activity状态,包括内部view中状态。这种状态下,activity会进行销毁并重建,activity生命周期会发生变化,调用顺序

    onPause-->onStop-->onDestroy

    由于系统是由于异常销毁,此时会先调用onSaveInstanceState方法,该方法会在onStop之前进行调用,但不一定在onPause之前或之后,然后在横屏后,activity调用onCreate进行重建,然后调用onRestoreInstanceState进行activity状态恢复。如果想要了解avtivity中view的状态缓存与恢复,可以看下view中的onSaveInstanceState方法的具体实现,这里就不粘贴出代码了,有兴趣的自行查看。
    贴出activity由竖屏切换到横屏的声明周期变化

    09-14 11:11:29.207 5716-5716/sunhailong01.myandroidp D/codebear: onSaveInstanceState
    09-14 11:11:29.212 5716-5716/sunhailong01.myandroidp D/codebear: onStop
    onDestroy
    09-14 11:11:29.250 5716-5716/sunhailong01.myandroidp D/codebear: onCreate
    09-14 11:11:29.263 5716-5716/sunhailong01.myandroidp D/codebear: onStart
    09-14 11:11:29.335 5716-5716/sunhailong01.myandroidp D/codebear: onRestoreInstanceState
    09-14 11:11:29.382 5716-5716/sunhailong01.myandroidp D/codebear: onResume

    onSaveInstanceState调用栈如下

    image.png

    Avtivity的onSaveInstanceState的实现如下

    protected void onSaveInstanceState(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);
    }
    getApplication().dispatchActivitySaveInstanceState(this, outState);
    }

    先说结论

    子类avtivity委托父类activity进行状态缓存实现,而父类activity的onSaveInstanceState中委托给appllacation进行SaveInstanceState的事件分发,而Applaction委托windosw(为什么是window往后看会有解释)分发,windows最终会委托最顶层的view进行状态缓存事件分发,顶层view通知各内部子view进行具体事件分发的实现。

    再看实现

    Textview的onSaveInstance的具体实现如下

    @Override
    public Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();
    // Save state if we are forced to
    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) {
    // Or save state if there is a selection
    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) {
    // XXX Should also save the current scroll position!
    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;
    }

    最后贴出textView的onSaveInstanceState方法调用栈,一切就明了了

    image.png

    再来看下状态是如何恢复的

    onRestoreInstanceState 调用栈如下

    image.png

    Avtivity的onRestoreInstanceState的实现如下

    protected void onRestoreInstanceState(Bundle savedInstanceState) {
    if (mWindow != null) {
    Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
    if (windowState != null) {
    mWindow.restoreHierarchyState(windowState); // 这里使用了window进行了状态恢复,所以状态的缓存最终也是通过window进行缓存事件分发
    }
    }
    }

    TextView的onRestoreInstanceState方法实现如下

    public void onRestoreInstanceState(Parcelable state) {
    if (!(state instanceof SavedState)) {
    super.onRestoreInstanceState(state);
    return;
    }
    SavedState ss = (SavedState) state;
    super.onRestoreInstanceState(ss.getSuperState());
    // XXX restore buffer type too, as well as lots of other stuff
    if (ss.text != null) {
    setText(ss.text);
    }
    if (ss.selStart >= 0 && ss.selEnd >= 0) {
    if (mText instanceof Spannable) {
    int len = mText.length();
    if (ss.selStart > len || ss.selEnd > len) {
    String restored = "";
    if (ss.text != null) {
    restored = "(restored) ";
    }
    Log.e(LOG_TAG, "Saved cursor position " + ss.selStart + "/" + ss.selEnd
    + " out of range for " + restored + "text " + mText);
    } else {
    Selection.setSelection((Spannable) mText, ss.selStart, ss.selEnd);
    if (ss.frozenWithFocus) {
    createEditorIfNeeded();
    mEditor.mFrozenWithFocus = true;
    }
    }
    }
    }
    if (ss.error != null) {
    final CharSequence error = ss.error;
    // Display the error later, after the first layout pass
    post(new Runnable() {
    public void run() {
    if (mEditor == null || !mEditor.mErrorWasChanged) {
    setError(error);
    }
    }
    });
    }
    if (ss.editorState != null) {
    createEditorIfNeeded();
    mEditor.restoreInstanceState(ss.editorState);
    }
    }

    最后贴出textView的onRestoreInstanceState方法调用栈,一切就又明了了

    image.png

    至此,我们了解了onSaveInstance的调用时机、实现逻辑、调用顺序。

    相关文章

      网友评论

          本文标题:onSaveInstanceState与onRestoreIns

          本文链接:https://www.haomeiwen.com/subject/rzangftx.html