DialogFragment使用中show()方法遇到的IllegalStateException

DialogFragment在Activity执行onSaveInstanceState完成后调用show报BUG的解决方案 在开发过程中,发现了这样一个BUG:在用DialogFragment的show(FragmentTransaction transaction,String tag)方法时会报如下BUG:(中间空白为项目代码请忽律)  java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 阅读详情
原文地址为: DialogFragment使用中show()方法遇到的IllegalStateException

  最近在首页做了一个弹窗,用dialogFragment 实现的,线上报了一个crash:

ava.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1493)
特此记录一下。

此问题的原因是:mainActivity 调用了onSaveInstanceState()以后有触发了dialog的显示,dialog.show()方法里边用的是commit()而不是commitAllowingStateLoss()

追踪一下代码:

DialogFragment中:

public void show(FragmentManager manager, String tag) {
mDismissed = false;
mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();
}

从调用下手:

dialog.show(getActivity().getSupportFragmentManager(), "");

可以追踪下去,第一个参数manager是:
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
FragmentTransaction ft = manager.beginTransaction();
 @Override    public FragmentTransaction beginTransaction() {        return new BackStackRecord(this);    }

BackStackRecord中:

public int commit() {
return commitInternal(false);
}

public int commitAllowingStateLoss() {
return commitInternal(true);
}

可以看到这俩函数的区别就是commitInternal()方法中参数一个为true,一个为false,看一下这个函数:

int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
dump(" ", null, pw, null);
}
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
再追踪到enqueueAction(this,allowStateLoss):

public void enqueueAction(Runnable action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<Runnable>();
}
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
可以看到函数第一行根据allowStateLoss做了一个判断,看一下checkStateLoss():

private void checkStateLoss() {
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}

怎么样,终于把这个异常信息给抓出来了吧,特么的,

知道了bug原因那我们来说一下解决吧,有人说用反射的方法拿到commitAllowingStateLoss()方法,调用他,但是这也太麻烦了,所简单点的办法就是:

重写show方法catch住异常即可,做好容错处理:

 /**
* 为了解决:mainActivity调用onSaveInstanceState以后又调用了show方法,
* 出现的Can not perform this action after onSaveInstanceState
* 这个异常(不应该用commit ,而是用commitAllowingStateLoss)
* 得罪了,不会反射 ,先把你catch住吧.乖
* @param manager
* @param tag
*/
@Override
public void show(FragmentManager manager, String tag) {
try {
super.show(manager, tag);
} catch (IllegalStateException ignore) {
// 容错处理,不做操作
}
}

另外别忘记dissmiss也要做处理:

/**
* 注意,不要用super.dismiss(),bug 同上show()
* super.onDismiss就没问题
*/
public void dismissDialog() {
if ( getActivity() != null && !getActivity().isFinishing()) {
super.dismissAllowingStateLoss();
}
}
而这个方法是没问题的:

@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
}
因为他调用的就是:

public void onDismiss(DialogInterface dialog) {
if (!mViewDestroyed) {
// Note: we need to use allowStateLoss, because the dialog
// dispatches this asynchronously so we can receive the call
// after the activity is paused. Worst case, when the user comes
// back to the activity they see the dialog again.
dismissInternal(true);
}
}
好了,特此纪念一下,再犯此错误,





转载请注明本文地址: DialogFragment使用中show()方法遇到的IllegalStateException
多目标跟踪中使用trackeval评估dancetrack运行结果 trackeval使用 阅读详情

相关推荐

FPGA实战:AXI BRAM Controller写时序避坑指南(附Vivado配置步骤)

本文深入探讨了FPGA开发中AXI BRAM Controller的写时序实战要点与常见陷阱。文章聚焦于写地址与写数据通道的握手机制,详细解析了AWREADY、WVALID等关键信号的处理,并提供了Vivado中流水线深度、ECC等关键参数的配置步骤与优化建议,旨在帮助开发者有效规避时序问题,提升系统性能。

weixin_32306683的博客 170

FragmentManager has been destroyed

FragmentManager has been destroyed

ss520k的专栏 1881

【SWAT水文模型】SWAT-CUP参数率定与模型验证实战指南

本文提供了SWAT水文模型参数率定与模型验证的完整实战指南。详细介绍了如何使用SWAT-CUP工具,特别是SUFI-2算法,进行自动化参数校准,并阐述了模型验证的关键步骤以避免过度拟合。内容涵盖从工程搭建、核心参数选择、迭代优化到结果分析与常见问题排查的全流程,旨在帮助用户提升SWAT模型模拟的准确性与可靠性。

weixin_29072299的博客 499

Fragment嵌套Fragment多次切换两次会出现Activity has been destroyed错误的解决办法

在嵌套子Fragment中的onDetach()方法中增加代码如下: @Override     public void onDetach()     {         super.onDetach();         try         {             Field childFragmentManager = Fragment.class.getDeclared

baiyi168的专栏 3879

WRF-CHEM 新手向实践(四):化学初始/边界场及namelist设置

这是这个系列的最后一节了,这些经验是自己作为一个半路出家的外行一步步摸索出来的,其中不免有很多理解不到位的地方,但也正是如此,我相信这是目前新手入门wrf-chem最友好的教程之一,希望能对大家有实质性的帮助。本节继续未完成的内容。在mozbc生成化学初始和边界条件之前,还需要先在wrfinput文件中开启化学部分。

qq_42335815的博客 4638

C#实现网络寻路(附完整源码)

C#实现网络寻路(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 423

解决Fragment相关问题,java-lang-illegalstateexception-activity-has-been-destroyed

开发时代码设计如下:FragmentActivity包含一个Fragment A ,B,C, 该Fragment A 中包含一个Viewpager+FragmentPagerAdapter的组合,当在Fragment A,B,C中切换时,遇到遇到以下错误 错误1:java.lang.IllegalStateException: Recursive entry to executePendingT

vk5176891的专栏 1万+

RTCA DO-160G标准详解:航空电子设备的全面环境适应性测试指南

第二章的主要目的是提供标准中使用的术语和定义。了解这些术语对于准确理解标准的要求至关重要,特别是在技术实施过程中。RTCA DO-160G 涉及多个学科的知识,包括航空、电子、电磁学和机械工程,因此需要确保使用的术语在所有学科中具有一致的定义。为了确保测试人员和工程师在执行测试时对所有条件和要求的理解一致,RTCA DO-160G 标准中定义了大量术语。环境应力:指的是设备在操作过程中可能遇到的外部物理或化学条件,包括温度、湿度、振动等。电磁干扰(EMI)

qq_41854911的博客 5277

DialogFragment调用show()报Can not perform this action after onSaveInstanceState的解决办法

DialogFragment调用show()报Can not perform this action after onSaveInstanceState的解决办法 参考文章: 使用自定义DialogFragment出现IllegalStateException: Can not perform this action after onSaveInstanceState异常 Fragment Or...

Maxwell 3074

博途PLC S7-1200/1500 ModbusTcp通信SCL代码篇(轮询)

博途PLC MODBUS TCP的详细讲解和注意事项,可以参看下面这篇博文,这里不在赘述。这篇作为SCL代码篇主要给出SCL语言下的轮训写法和注意事项。博途PLC1200/1500PLC ModbusTcp通信(轮询处理)_RXXW_Dor的博客-优快云博客。............

RXXW_Dor的博客 8425

《QGIS快速入门与应用基础》010:下载过程中常见问题(如网速慢、文件损坏)

针对QGIS下载过程中的常见问题提供了系统解决方案。主要解决下载速度慢(≤100KB/s)和文件损坏两大核心问题:通过切换国内镜像源(如清华大学、阿里云)、使用专业下载工具提升速度;采用MD5/SHA256校验确保文件完整性,并排查存储介质和杀毒软件干扰。文章还包含macOS权限问题、Linux依赖缺失等高频问题的速解方案,并附详细的排查流程图和预防技巧,帮助用户顺利完成QGIS下载。后续将详细介绍安装流程,适合零基础用户参考。

LuckyHanMo的博客 482

Android DialogFragment 异常报错:java.lang.IllegalStateException: Fragment already added: XxxDialog

DialogFragment 在使用中,由于点击过快或者多次创建导致异常报错!

吕氏春秋i 1125

[明道云] -基础教学1- 创建第一个工作表:从 0 到实用

明道云工作表相当于数据库表,是存储业务数据的核心组件。创建工作表主要有两种方式:1)从空白新建,通过添加字段(最多200个)、设置属性、配置表单样式;2)从Excel导入,需选择sheet、配置字段映射。创建后系统自动生成默认视图,支持多种视图形式(看板/日历等)。建议设置合适的标题字段和关联关系,初学者可在一小时内完成基础应用搭建。后续可扩展权限控制、工作流自动化等功能。

每日出拳老爷子的博客 556

官方推荐的Dialog——DialogFragment

简介 官方推荐使用的Dialog类型,继承自Fragment,通过FragmentManager管理对话弹框。由于继承自Fragment,使用dialog时完全可以将其看作Fragment。 使用DialogFragment需要实现onCreateView()、onCreateDialog()其中之一。 onCreateView即将完全自定义一个dialog。 onCreateDialog

ffengz的博客 1831

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

DialogFragment源码分析

目录介绍 1.最简单的使用方法 1.1 官方建议 1.2 最简单的使用方法 1.3 DialogFragment做屏幕适配 2.源码分析 2.1 DialogFragment继承Fragment 2.2 onCreate(@Nullable Bundle savedInstanceState)源码分析 2.3 setStyle(@DialogStyle int style, @StyleR...

weixin_33975951的博客 163

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

IllegalStateException: Fragment not attached to a context.

问题: java.lang.IllegalStateException: Fragment <...>not attached to a context. 根源: fragment 没有和 activity绑定,context为空. 参考: Fragment.java @NonNull public final Context requireContext() { ...

yubing1015的博客 6012

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

@data 重写set方法_关于DialogFragment的show()方法抛异常

关于DialogFragment抛出java.lang.IllegalStateExceptionCan not perform this action after onSaveInstanceState异常:onSaveInstanceState方法是在Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后 再给它添加Fragment就会出错。看源码我们可以发现这个异...

weixin_35809747的博客 233

DialogFragment 使用过程中出现 java.lang.IllegalStateException 问题的解决方法

在使用 DialogFragment 的过程中会偶现java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 的问题,具体错误日志如下 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManag.

syyyzld的博客 2135

解决DialogFragment调用show方法报错问题

在Android 3.0以后,Google官方推荐使用DialogFragment代替Dialog使用,但是这个有个bug,就是DialogFragment调用show方法会出现Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState这个恶心的错误,如何解决呢?...

andy092835的博客 4455

DialogFragment 使用时出现IllegalStateException: Can not perform this action after onSaveInstanceState

今天收到一个问题,检索日志后,看到了如下的错误提示: AndroidRuntime: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState AndroidRuntime: at android.support.v4.app.FragmentManagerImpl.c...

mahongy的博客 809

DialogFragment里 public void show(FragmentManager manager, String tag)报错问题

问题: DialogFragment里 在调用show(FragmentManager manager, String tag)时候报错 原因: 查看源码show方法如下 public void show(FragmentManager manager, String tag) { this.mDismissed = false; this....

Gufra_Yin的博客 783
上一篇: 如何计算时间复杂度
下一篇: 用Gradle 构建你的android程序
dearbaba_8520
博客等级 码龄9年 406粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值