使用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的有效赋值只在BackStackRecordFragmentManagerFragmentLayoutInflaterFactory三个类中

然后我们重新从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相关推荐

  1. #iOS问题记录#WKWebView 闪退异常

    #iOS问题记录#WKWebView 闪退异常 参考文章: (1)#iOS问题记录#WKWebView 闪退异常 (2)https://www.cnblogs.com/Sanje3000/p/6953 ...

  2. iOS端(腾讯Bugly)闪退异常上报扑获日志集成与使用指南

    app已经上架并且有三次更新版本,今天市场部和顾客约谈时,发现顾客的iphone 6 plus iOS 9.0.2上运行app点击登录按钮时直接闪退,无法进入app里,这个问题还是第一次遇到,我下载了 ...

  3. Android应用闪退异常java.lang.RuntimeException: Unable to instantiate application

    1.闪退异常的出现 开发过程中测试的时候一般都是打的debug包来测试,但是昨天打的debug包突然出现一个很棘手的问题,一直没找到原因,本来项目在手机上直接部署是没问题的,但是打个debug包给测试 ...

  4. 苹果手机软件闪退怎么解决_《NBA2K21》闪退怎么办 闪退异常问题解决方法

    导读 相信很多小伙伴在游玩<NBA 2K21>时都出现了闪退的问题,但是却不清楚要怎么解决,所以小编这次就为大家带来了<NBA 2K21>闪退解决方法介绍,有需要的小伙伴可以来 ...

  5. React-Native 关于oppo手机闪退的问题

    刚刚学习React-Native,感谢前人挖井,今天有一点自己的收获,写下来回报社会; 1.oppo手机安装应用闪退, 异常日志:RuntimeException: Unable to instant ...

  6. 华为手机 android8.0APP更新时出现安装包解析异常的提示及安装闪退(无反应)问题

    华为手机 android8.0APP更新时出现安装包解析异常的提示及安装闪退(无反应)问题 参考文章: (1)华为手机 android8.0APP更新时出现安装包解析异常的提示及安装闪退(无反应)问题 ...

  7. CAD异常闪退的原因

    2019独角兽企业重金招聘Python工程师标准>>> 无论你用的是哪款软件,都会遇到出现异常闪退的情况,在这种情况下,有的是前功尽弃,之前做的文件没了,白白浪费了时间,有的则是干着 ...

  8. 谷歌浏览器问题事件BEX和浏览器闪退崩溃异常解决

    谷歌浏览器问题事件BEX和浏览器闪退崩溃问题 问题一:问题事件BEX浏览器停止工作 原因 解决 删除造成冲突的dll文件 修复造成冲突的软件 问题二:谷歌浏览器闪退 原因 解决 删除安全策略 增加用户 ...

  9. 安装升级包卡住了华为_华为手机 android8.0APP更新时出现安装包解析异常的提示及安装闪退(无反应)问题...

    在做android app升级更新时遇到几个问题,我用的测试机是华为V10 系统为8.0 一.安装闪退(无反应) 解决办法: 只要在Mainfest.xml 中加入权限编码即可解决 来源参考:http ...

  10. 星河战神显示服务器异常,腾讯星河战神黑屏闪退怎么解决

    腾讯星河战神黑屏闪退怎么解决?星河战神是腾讯继雷霆战机之后推出的又一款飞行射击游戏,出现黑屏闪退问题是非常难免的,接下来小编就给大家介绍一下星河战神闪退黑屏解决方法. 腾讯星河战神黑屏闪退怎么解决?星 ...

最新文章

  1. php jq ajax 4个下拉框联动案列,Ajax与Jquery结合数据库做出实现下拉框的二级联动...
  2. stm32f10x_it.c 定义的程序列表模板(stm32f103x_it.c中放的是中断的空函数)
  3. 使用memcache缓存
  4. SAP UI5 main page design
  5. 合成孔径雷达_合成孔径雷达(SAR)基础:汇总
  6. 作者:刘玮(1977-),男,中国科学院计算技术研究所网络数据中心、烟台中科网络技术研究所工程师。...
  7. 变形金刚热映黑客借机“下毒” 用户谨防木马
  8. gephi 使用mysql数据,gephi练习数据
  9. docker 镜像导入导出
  10. varied字符串c语言,C语言输入输出问题解析研究.pdf
  11. 人员优化浪潮下,苟住要紧。
  12. PHP mcrypt可逆加密算法分析
  13. 【目标检测】目标检测中的多尺度检测(Multi-Scale),FPN,RPN
  14. windows库的创建和使用:静态库+动态库
  15. APP性能测试之monkey
  16. 设计模式(一)——设计模式的七大原则
  17. Ubuntu下安装日语输入法
  18. 组合逻辑设计中的毛刺现象
  19. 电脑耳机拔出后,再插入没声音
  20. GEE:LST地表温度反演函数(针对Landsat8的T1影像和T1_L2影像集合)

热门文章

  1. 星界边境Starbound创意工坊订阅的mod的存放路径
  2. Win32SDK基本 RC资源的使用
  3. 用后台开发的逻辑理念学习VUE
  4. 优惠券管理--优惠券类型
  5. 纳什均衡(Nash equilibrium)及经典案例
  6. 云杰恒指:期货交易操盘手是怎样的体验?
  7. 许三多的 “职业精神”
  8. 使用迅雷下载百度云盘数据
  9. Python-批处理修改音频采样率(批量重采样)
  10. 相对定位(relative)和绝对定位(absolute)的区别