DialogFragment dismiss闪退异常DialogFragment何时持有FragmentManager
使用DialogFragment如果在没有调用过show方法时调用dismiss方法,就会出现异常
java.lang.IllegalStateException: Fragment DialogFragmentName(你自己的类名) not associated with a fragment manager.
提示就是没有FragmentManager
public class DialogFragment extends Fragment{public void dismiss() {dismissInternal(false, false);//可以看到直接调用了dismissInternal方法,这也是DialogFragment中的方法}void dismissInternal(boolean allowStateLoss, boolean fromOnDismiss) { //...//上面有一部分代码,和我们遇到的异常无关//下面进入了一个if语句,不管是进入if还是else//都要调用getParentFragmentManager方法if (mBackStackId >= 0) {getParentFragmentManager().popBackStack(mBackStackId,FragmentManager.POP_BACK_STACK_INCLUSIVE);//...} else {FragmentTransaction ft = getParentFragmentManager().beginTransaction();//...}//...}
getParentFragmentManager()
是Fragment的方法,会返回Fragment的mFragmentManager对象,当mFragmentManager为null时,就会抛出我们遇到的异常
@NonNullpublic final FragmentManager getParentFragmentManager() {FragmentManager fragmentManager = mFragmentManager;if (fragmentManager == null) {throw new IllegalStateException("Fragment " + this + " not associated with a fragment manager.");}return fragmentManager;}
DialogFragment.dismiss->DialogFragment.dismissInternal->Fragment.getParentFragmentManager,最终因为Fragment的mFragmentManager变量是null导致抛出异常。
怎么才能让这个变量不是null呢,答案是在调用DialogFragment.show方法时需要传入一个FragmentManager对象作为参数,最终这个对象会被赋值给当前DialogFragment的mFragmentManager变量,之后再调用dismiss方法也不会抛出异常了
解决方法:
避免在没有DialogFramgent没有show过的情况下调用dismiss
或是重写dismiss方法,手动判断在mFragmentManager不为null时才dismiss
@Overridepublic void dismiss() {if (getFragmentManager()==null){Log.w(TAG, "dismiss: "+this+" not associated with a fragment manager." );}else {super.dismiss();}}
番外:show方法是怎么给Fragment的mFragmentManager变量赋值的?
顺便分享一下自己追代码的方式。
先试着正着跟了一下,FragmentManager和BackStackRecord来回跳,基本追了几层就放弃了,选择先倒着看一下,也就是看下Fragment的mFragmentManager在什么地方赋值,来找点线索或者目标,我们不用弄清楚每个赋值的方法具体做了什么,只要往上追两层,对相关方法的名字或者相应的动作有印象就好了。
可以看到,Fragment的mFragmentManager的有效赋值只在BackStackRecord
、FragmentManager
和FragmentLayoutInflaterFactory
三个类中
然后我们重新从show方法开始追下去,如果追到这三个类之外的方法,并且方法参数不是这三个类的话(如果是这三个类,可能还会转回来),基本就可以放弃了,可以少追很多无效代码
DialogFragment.show(FragmentManager manager)
FragmentTransaction ft = manager.beginTransaction();//直接返回一个BackStackRecord对象,它是抽象类FragmentTransaction的唯一实现类ft.add(this, tag);//把当前的DialogFragment(是Fragment的子类)封装到一个对象里,并添加到ft对象持有的集合中ft.commit();//跟进去
BackStateRecord.commit()&commitInteral()
commit是FragmentTranslation中定义的抽象方法,BackStateRecord对它的实现是直接调用自己的commitInteral方法
int commitInternal(boolean allowStateLoss) {//...mManager.enqueueAction(this, allowStateLoss);//跟进去,有经验的话,看到这个方法名字就觉得很可能是它。可能接收的参数就是一个类似Runnable的实现类,在调用 类似run()的方法时,还是要去这个实现类中看逻辑的//but!很可惜,这里给Fragemnt设置FragemtnManager和这个this参数无关哈哈//...}
FragmentManager.enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss)
void enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss) {synchronized (mPendingActions) {mPendingActions.add(action);//与Fragment设置FragmentManager无关,大概看了下,是用来打印log的scheduleCommit();//跟进去}}
FragmentManager.scheduleCommit()
void scheduleCommit() {//...mHost.getHandler().removeCallbacks(mExecCommit);//看名字就不用管mHost.getHandler().post(mExecCommit);//post,这个参数是一个Runnable,看下它的run方法updateOnBackPressedCallbackEnabled();//点进去看一眼,是设置了某个回调是否启用,跟这个方法的话需要继续去看这个回调的逻辑,优先级比较低,没办法了再去看它/...}private Runnable mExecCommit = new Runnable() {@Overridepublic void run() {execPendingActions(true);}};
FragmentManager.execPendingActions
boolean execPendingActions(boolean allowStateLoss) {ensureExecReady(allowStateLoss);//由于之前倒着追的时候,对这个方法名或类似的名字有印象,所以我选择直接跟这个方法,如果无效的话再看后面的//...}
FragmentManager.ensureExecReady()
private void ensureExecReady(boolean allowStateLoss) {//...executePostponedTransaction(null, null);//...}
FragmentManager.executePostponedTransaction
private void executePostponedTransaction(@Nullable ArrayList<BackStackRecord> records,@Nullable ArrayList<Boolean> isRecordPop) {//...if (records != null && !listener.mIsBack&& (index = records.indexOf(listener.mRecord)) != -1&& isRecordPop != null&& isRecordPop.get(index)) {// This is popping a postponed transactionlistener.cancelTransaction();//这是倒着追的时候看到过的方法} else {listener.completeTransaction();//这也是倒着追的时候看到过的方法}}}}
看到这里,基本可以确定就是这个方法里进行的赋值了
他们两个方法都调用了mRecord.mManager.completeExecute
这个方法
void completeExecute(@NonNull BackStackRecord record, boolean isPop, boolean runTransitions,boolean moveToState) {if (isPop) {record.executePopOps(moveToState);//倒着追看到过} else {record.executeOps();//也看到过}}
这两个BackStackRecord类中的方法点进去,都是进行了一个类似的switch语句,其中会遍历DialogFragment.show()-
> ft.add()
中的集合,这个集合中的对象是持有一个Fragment的;
最后一步冲刺!!
BackStackRecord.executeOps()
switch (op.mCmd) {case OP_ADD:f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);mManager.setExitAnimationOrder(f, false);mManager.addFragment(f);//就是它break;case OP_REMOVE:f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);mManager.removeFragment(f);break;//...
DialogFragment dismiss闪退异常DialogFragment何时持有FragmentManager相关推荐
- #iOS问题记录#WKWebView 闪退异常
#iOS问题记录#WKWebView 闪退异常 参考文章: (1)#iOS问题记录#WKWebView 闪退异常 (2)https://www.cnblogs.com/Sanje3000/p/6953 ...
- iOS端(腾讯Bugly)闪退异常上报扑获日志集成与使用指南
app已经上架并且有三次更新版本,今天市场部和顾客约谈时,发现顾客的iphone 6 plus iOS 9.0.2上运行app点击登录按钮时直接闪退,无法进入app里,这个问题还是第一次遇到,我下载了 ...
- Android应用闪退异常java.lang.RuntimeException: Unable to instantiate application
1.闪退异常的出现 开发过程中测试的时候一般都是打的debug包来测试,但是昨天打的debug包突然出现一个很棘手的问题,一直没找到原因,本来项目在手机上直接部署是没问题的,但是打个debug包给测试 ...
- 苹果手机软件闪退怎么解决_《NBA2K21》闪退怎么办 闪退异常问题解决方法
导读 相信很多小伙伴在游玩<NBA 2K21>时都出现了闪退的问题,但是却不清楚要怎么解决,所以小编这次就为大家带来了<NBA 2K21>闪退解决方法介绍,有需要的小伙伴可以来 ...
- React-Native 关于oppo手机闪退的问题
刚刚学习React-Native,感谢前人挖井,今天有一点自己的收获,写下来回报社会; 1.oppo手机安装应用闪退, 异常日志:RuntimeException: Unable to instant ...
- 华为手机 android8.0APP更新时出现安装包解析异常的提示及安装闪退(无反应)问题
华为手机 android8.0APP更新时出现安装包解析异常的提示及安装闪退(无反应)问题 参考文章: (1)华为手机 android8.0APP更新时出现安装包解析异常的提示及安装闪退(无反应)问题 ...
- CAD异常闪退的原因
2019独角兽企业重金招聘Python工程师标准>>> 无论你用的是哪款软件,都会遇到出现异常闪退的情况,在这种情况下,有的是前功尽弃,之前做的文件没了,白白浪费了时间,有的则是干着 ...
- 谷歌浏览器问题事件BEX和浏览器闪退崩溃异常解决
谷歌浏览器问题事件BEX和浏览器闪退崩溃问题 问题一:问题事件BEX浏览器停止工作 原因 解决 删除造成冲突的dll文件 修复造成冲突的软件 问题二:谷歌浏览器闪退 原因 解决 删除安全策略 增加用户 ...
- 安装升级包卡住了华为_华为手机 android8.0APP更新时出现安装包解析异常的提示及安装闪退(无反应)问题...
在做android app升级更新时遇到几个问题,我用的测试机是华为V10 系统为8.0 一.安装闪退(无反应) 解决办法: 只要在Mainfest.xml 中加入权限编码即可解决 来源参考:http ...
- 星河战神显示服务器异常,腾讯星河战神黑屏闪退怎么解决
腾讯星河战神黑屏闪退怎么解决?星河战神是腾讯继雷霆战机之后推出的又一款飞行射击游戏,出现黑屏闪退问题是非常难免的,接下来小编就给大家介绍一下星河战神闪退黑屏解决方法. 腾讯星河战神黑屏闪退怎么解决?星 ...
最新文章
- php jq ajax 4个下拉框联动案列,Ajax与Jquery结合数据库做出实现下拉框的二级联动...
- stm32f10x_it.c 定义的程序列表模板(stm32f103x_it.c中放的是中断的空函数)
- 使用memcache缓存
- SAP UI5 main page design
- 合成孔径雷达_合成孔径雷达(SAR)基础:汇总
- 作者:刘玮(1977-),男,中国科学院计算技术研究所网络数据中心、烟台中科网络技术研究所工程师。...
- 变形金刚热映黑客借机“下毒” 用户谨防木马
- gephi 使用mysql数据,gephi练习数据
- docker 镜像导入导出
- varied字符串c语言,C语言输入输出问题解析研究.pdf
- 人员优化浪潮下,苟住要紧。
- PHP mcrypt可逆加密算法分析
- 【目标检测】目标检测中的多尺度检测(Multi-Scale),FPN,RPN
- windows库的创建和使用:静态库+动态库
- APP性能测试之monkey
- 设计模式(一)——设计模式的七大原则
- Ubuntu下安装日语输入法
- 组合逻辑设计中的毛刺现象
- 电脑耳机拔出后,再插入没声音
- GEE:LST地表温度反演函数(针对Landsat8的T1影像和T1_L2影像集合)