Android 屏幕旋转问题&onSaveInstanceState初探(1)

在屏幕旋转Activity重建时 测试环境:Android10 一加6 onSaveInstanceState的展示时机跟其他文章有出入

D/PRETTY_LOGGER: │ MainActivityX onPause
D/PRETTY_LOGGER: │ MainActivityX onStop
D/PRETTY_LOGGER: │ MainActivityX onSaveInstanceState
D/PRETTY_LOGGER: │ MainActivityX onDestroy

重建后:

D/PRETTY_LOGGER: │ MainActivityX onCreate
D/PRETTY_LOGGER: │ MainActivityX onStart
D/PRETTY_LOGGER: │ MainActivityX onRestoreInstanceState
D/PRETTY_LOGGER: │ MainActivityX onResume

屏幕旋转,默认情况下Activity会进行重建。
避免Activity重建:
给 Activity添加android:configChanges="orientation|screenSize"属性
或者禁止旋转 android:screenOrientation=“portrait” 或者在代码中添加

fun onSaveInstanceState(outState: Bundle)
作用:保存信息和数据 在onDestroy()之前调用
被调用的时机 :当前界面息屏、Home键、屏幕旋转

fun onRestoreInstanceState(savedInstanceState: Bundle)
作用:可以用作恢复数据疑问:onCreate()里也有Bundle数据可以初始化,有什么不同? 在onStart()和onResume()之间调用。onCreate中的Bundle可能为空,根据需求选择数据恢复时机在哪。

疑问:都说Intent的Bundle传递数据量最大是1M-8K,那么保存的Bundle的数据也受限制吗?根据他人的描述,可能会出现问题,所以还是使用相同的解决方法,将数据放在数据库或者文件等形式保存

疑问:Activity的onSaveInstanceState保存了什么?
Activity.java

//保存了View树和Fragment的数据
 protected void onSaveInstanceState(@NonNull Bundle outState) {
 		//View树的数据
        outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
        outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
        //Fragment的数据
        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);
    }

最终执行到:
View.java

protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
            Parcelable state = onSaveInstanceState();
            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
                throw new IllegalStateException(
                        "Derived class did not call super.onSaveInstanceState()");
            }
            if (state != null) {
                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
                // + ": " + state);
                container.put(mID, state);
            }
        }
    }
 @Nullable protected Parcelable onSaveInstanceState() {
        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
        if (mStartActivityRequestWho != null || isAutofilled()
                || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);

            if (mStartActivityRequestWho != null) {
                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
            }

            if (isAutofilled()) {
                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
            }

            if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
                state.mSavedData |= BaseSavedState.AUTOFILL_ID;
            }

            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
            state.mIsAutofilled = isAutofilled();
            state.mAutofillViewId = mAutofillViewId;
            return state;
        }
        return BaseSavedState.EMPTY_STATE;
    }

使用例子:
TextView.java 重载onSaveInstanceState()

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

疑问:Activity里的Fragment要怎么处理?

参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值