Fragment Or DialogFragment Can not perform this action after onSaveInstanceState

简介: 转载自Fragment Or DialogFragment Can not perform this action after onSaveInstanceState表现可会造成app崩溃掉,具体日志如下: 异常如下:java.

转载自Fragment Or DialogFragment Can not perform this action after onSaveInstanceState

表现

可会造成app崩溃掉,具体日志如下:

异常如下:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
            at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1323)
            at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1341)
            at android.app.BackStackRecord.commitInternal(BackStackRecord.java:597)
            at android.app.BackStackRecord.commit(BackStackRecord.java:575)
            at android.app.DialogFragment.show(DialogFragment.java:230)
            at com.github.afeita.net.ext.TipsingNetCallback.onStart(TipsingNetCallback.java:55)
            at com.github.afeita.net.ext.AfeitaNet$3.onStart(AfeitaNet.java:567)
            at com.github.afeita.net.ext.request.CacheRequest.deliverOnStart(CacheRequest.java:260)
            at com.github.afeita.net.ExecutorDelivery$4.run(ExecutorDelivery.java:116)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
AI 代码解读

场景

这与不洽当的使用Fragment有关系,其实不光时DialogFragment,Fragment也有的。当:

  • A activity页面中,需要异步通知B activity去更新或do something然后A再do 自己的(A)的something,而这让B do something洽好是切换Fragment的话(此时又回到A中自己在do something),那么就可以出现这个异常。
  • activity页面 某个原因要切换到后台中了,系统调用了onSaveInstanceState,此时之后异步任务来了,是需要show或dismiss一个DialogFragment也会报这个异常。

总之是:在onSaveInstanceState后执行了commit抛出的。

原因

上面的异常,跟踪上去是DialogFragment.show方法中报出来,好么查看下源码,这个show里用做什么,抛出这个异常的呢。

public void show(FragmentManager manager, String tag) {
        mDismissed = false;
        mShownByMe = true;
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commit(); //注意这里使用提commit
    }
AI 代码解读

解决方法:

对于肯定会出现这种需求的,比如网络请求访问弹出的加载中…提示DialogFragment。
那么,不采用系统默认的show方法 显示对话框。采用自己用 FragmentTransaction控制,示例如下:

FragmentTransaction ft = activity.getFragmentManager().beginTransaction();
                ft.add(dialogFragment, this.getClass().getSimpleName());
                ft.commitAllowingStateLoss();//注意这里使用commitAllowingStateLoss()
AI 代码解读

根据google对ft.commitAllowingStateLoss方法的说明:Like commit() but allows the commit to be executed after an activity’s state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.
这个方法是允许activity在state状态改变保存(onSaveInstanceState) 时允许commit。。。但也许不是很洽当,因为当activity onRestoreInstanceState恢复状态时commit可能会被丢掉了。恢复不了那次的commit了。使用这个方法应该确保存页面状态的改变对用户无感时。一般可以确认是即使页面需要重新onRestoreInstanceState时上次commit丢失的也不用管时就可以用了。

注意前面虽然说的是DialogFragment,也是Fragment因为这点并不是DialogFrament特例它属于Fragment不能在onSaveInstanceState,普通的commit。

若DialogFragment使用了ft.commitAllowingStateLoss,那么在关闭时使用dialogFragment.dismissAllowingStateLoss。

目录
打赏
0
0
0
0
11
分享
相关文章
解决圆形进度条ProgressBar的几个问题
Android自带的Progressbar默认就是圆形的,可以通过设置style属性 style="?android:attr/progressBarStyleHorizontal" 复制代码 这样就能变成条状进度条,如下: <ProgressBar android:layout_width="match_parent" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal"/>
1435 0
Android 使用VideoView播放本地视频详解
Android 使用VideoView播放本地视频详解
703 2
你真了解Android任务栈 Task 与启动模式吗?
你真了解Android任务栈 Task 与启动模式吗?
232 0
Android获取设备状态栏status bar高度的正确姿势
Android获取设备状态栏高度的正确姿势 正确代码方式: int height = 0; int resourceId = getApplicationContext().
6821 0
抱歉,Xposed真的可以为所欲为——终 · 庖丁解码(下)
Xposed的使用不难,API也就那些,难点是: 逆向弄清楚Hook APP的方法调用流程,怎么调,参数都是干嘛的等。 经过反复练习,逆向Hook一个普通的APP(非企业级加固)写出可用的Xposed插件早已驾轻就熟(主要是磨时间),但有一个顾虑一直萦绕心间:不知道Xposed底层的具体实现原理。Tips:Xposed通常只能 Hook java层 及 应用资源的替换,有两个实现版本:4.4前的Dalvik虚拟机实现 和 5.0后ART虚拟机实现,本文针对后者进行分析,同时搭配 Android 5.1.1_r6 源码食用。
1786 0
Android中如何动态的调整Dialog的背景深暗
在Android开发中,Dialog和DialogFragment可通过设置`Window`的`backgroundDimAmount`来控制背景变暗,突出对话框。在DialogFragment的`onCreateDialog`或`onViewCreated`中,获取`Dialog`的`Window`,设置`LayoutParams.dimAmount`(例如0.5f)并添加`FLAG_DIM_BEHIND`标志。要动态调整,可保存`LayoutParams`并在需要时更新。对于Dialog,创建时直接设置同样属性。还可以通过定义主题样式设置背景模糊程度。
270 7
Android FrameLayout子view居中(左居中,右居中)等
Android的布局FrameLayout默认是把布局内的子view堆砌在左上角,但是,可以通过设置子view的: android:layout_gravity 此参数控制子view的布局位置,实现FrameLayou...
2568 0
关于安卓DialogFragment使用(三)
关于安卓DialogFragment使用(三)
409 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问