【常见问题】Can not perform this action after onSaveInstanceState

本文深入解析onSaveInstanceState方法的作用及其实现原理,包括其在Activity生命周期中的调用时机、保存的数据类型以及如何避免在此方法后执行某些操作可能导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

onSaveInstanceState是干什么的呢?

通过该方法保留的实例状态数据,然后借助onCreate(Bundle) or onRestoreInstanceState(Bundle),我们可以将已被killed的activity恢复回来。用户界面状态能够通过onCreate(Bundle) or onRestoreInstanceState(Bundle)来恢复,

onSaveInstanceState一定会被调用,NO:

1.用户主动从B页面回退到A页面,B页面从栈中弹出,用户不会再回退到B页面,所以也不用去保存数据来恢复B
2.B页面展示在A页面上,如果A在B的生命周期内绝对不被销毁

onSaveInstanceState到底存了什么数据?

保存了继承体系中每个view(带id的)大部分实例状态 ,并且存储当前热点view的id.它默认只保存了一些UI view的状态信息,可以通过覆写该方法来存储一些想要保存的额外数据。
做了一个简单的demo,
这里写图片描述

当屏幕旋转的时候,发生activity的重建。通过查看bundle来看,系统收集了这些内容,

Bundle[
{
    android:views=
    {
        16908290=android.view.AbsSavedState$1@59774b2, 
        2131492954=android.view.AbsSavedState$1@59774b2, 
        2131492955=android.view.AbsSavedState$1@59774b2, 
        2131492956=android.support.v7.widget.Toolbar$SavedState@ab71c03, 
        2131492957=android.view.AbsSavedState$1@59774b2, 
        2131493008=TextView.SavedState{7d20780 start=7 end=7 text=fghhfgg
    }
}, 
android:focusedViewId=2131493008}]
2131493008=TextView.SavedState{7d20780 start=7 end=7 text=fghhfgg}

关于TextView有其当前输入的内容fghhfgg,key是该TextView的id,

android:focusedViewId=2131493008

接着保存当前焦点停留的view的id号,刚好就是上面的textView.

注:没有id的view是不会为其保存状态信息的

从设计上来看为什么要禁止onSaveInstanceState之后执行某种action

对于应用来说,他对自己的生杀大权并不是完全掌握,很容易因为内存紧张而被杀死,但是android系统并不希望这样带给用户一种不一致甚至突兀的感觉。

onSaveInstanceState的时机是?

If called, this method will occur before onStop(). There are no guarantees about whether it will occur before or after onPause().

根据官方的定义,onSaveInstanceState 会在onStop前调用,但是不保证是在onPause之前还是之后被调用。

当我按下home健的时候
这里写图片描述

可以看的出,onSaveInstanceState在页面回到后台的操作执行后会很快被调用的。几乎在页面还未完全消失之前就调用了。

异常产生的关键判断条件:mStateSaved

当Fm中的mStateSaved为true的时候,进行fragment相关操作的时候会产生异常。
这里写图片描述

mStateSaved被修改为true 的场景是:

onStop调用时
onSaveInstanceState 调用时

mStateSaved被修改为false的场景是:

onCreate
onActivityCreated
onStart
onResume

需要注意哪些地方呢?

不要在异步方法中操作fragment

异步方法的回调时机很可能会出现在onSaveInstanceState调用后。

谨慎使用onBackPressed()替换finish()

在onBackPressed间接的会去调用checkStateLoss()

不要在onActivityResult中操作fragment

这里写图片描述
在onStart中fm才将mStateSaved修改为false,在这之前任何的fragment操作必然导致state loss.

DialogFragment的show()操作

有人说覆写show,然后替换为commitAllowStateLoss,ok。但是回到“从设计上来看为什么要禁止onSaveInstanceState之后执行某种action”来看,如果crash非常少量,那我们给用户带来突兀感觉的代价几乎可以忽略不及,catch住这个异常未尝不可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值