自从Android3.0引入了Fragment之后,使用Activity去嵌套一些Fragment的做法也变得更加流行,这确实是Fragment带来的一些优点,比如说:Fragment可以使你能够将activity分离成多个可重用的组件,每个都有它自己的生命周期和UI,更重要的是Fragment解决了Activity间的切换不流畅,实现了一种轻量及的切换,但是在官方提供的android.support.v4包中,Fragment还是或多或少的存在一些BUG,今天就与大家分享一下这些BUG和解决方法。

Case 1:当使用Fragment去嵌套另外一些子Fragment的时候,我们需要去管理子Fragment,这时候需要调用ChildFragmentManager去管理这些子Fragment,由此可能产生的Exception主要是:   
java.lang.IllegalStateException: No activity

首先我们来分析一下Exception出现的原因:   
    通过DEBUG发现,当第一次从一个Activity启动Fragment,然后再去启动子Fragment的时候,存在指向Activity的变量,但当退出这些Fragment之后回到Activity,然后再进入Fragment的时候,这个变量变成null,这就很容易明了为什么抛出的异常是No activity

这个Exception是由什么原因造成的呢?如果想知道造成异常的原因,那就必须去看Fragment的相关代码,发现Fragment在detached之后都会被reset掉,但是它并没有对ChildFragmentManager做reset,所以会造成ChildFragmentManager的状态错误。

找到异常出现的原因后就可以很容易的去解决问题了,我们需要在Fragment被detached的时候去重置ChildFragmentManager,即:

@Override
  public void onDetach() {    super.onDetach();
    try {      Field childFragmentManager = Fragment.class
          .getDeclaredField("mChildFragmentManager");
      childFragmentManager.setAccessible(true);
      childFragmentManager.set(this, null);    } catch (NoSuchFieldException e) {      throw new RuntimeException(e);
    } catch (IllegalAccessException e) {      throw new RuntimeException(e);
    }
  }

Case 2:当我们从一个Activity启动了一个Fragment,然后在这个Fragment中又去实例化了一些子Fragment,在子Fragment中去有返回的启动了另外一个Activity,即通过startActivityForResult方式去启动,这时候造成的现象会是,子Fragment接收不到OnActivityResult,如果在子Fragment中是以getActivity.startActivityForResult方式启动,那么只有Activity会接收到OnActivityResult,如果是以getParentFragment.startActivityForResult方式启动,那么只有父Fragment能接收(此时Activity也能接收),但无论如何子Fragment接收不到OnActivityResult。

这是一个非常奇怪的现象,按理说,应该是让子Fragment接收到OnActivityResult才对,究竟是什么造成的呢?这是由于某位写代码的员工抱怨没发奖金,稍稍偷懒了,少写了一部分代码,没有考虑到Fragment再去嵌套Fragment的情况。

我们来看看FragmentActivity中的代码:

protected void onActivityResult(int requestCode, int resultCode, Intent data){this.mFragments.noteStateNotSaved();int index = requestCode >> 16;if (index != 0) {index--;if ((this.mFragments.mActive == null) || (index < 0) || (index >= this.mFragments.mActive.size())) {Log.w("FragmentActivity", "Activity result fragment index out of range: 0x" + Integer.toHexString(requestCode));return;}Fragment frag = (Fragment)this.mFragments.mActive.get(index);if (frag == null) {Log.w("FragmentActivity", "Activity result no fragment exists for index: 0x" + Integer.toHexString(requestCode));}else {frag.onActivityResult(requestCode & 0xFFFF, resultCode, data);}return;}super.onActivityResult(requestCode, resultCode, data);}

很显然,设计者把Fragment的下标+1左移16位来标记这个request是不是Fragment的,拿到result再解码出下标,直接取对应的Fragment,这样并没有去考虑对Fragment嵌套Fragment做一个Map映射,所以出现了这种BUG。

但是如果我们需要在OnActivityResult的时候处理一些事情的话,我们可以通过在子Fragment中以getParentFragment.startActivityForResult的方式来启动,然后在父Fragment中去接收数据,我们需要在子Fragment中提供一个方法,如:getResultData(Object obj),通过父Fragment中的子Fragment实例去调用这个方法,把相应的数据传过去,然后去更新子Fragment。

浅谈Android Fragment嵌套使用存在的一些BUG以及解决方法相关推荐

  1. 浅谈android网络框架——以课程格子的bug为例

    大家好! 在使用课程格子过程中 ,发现如果网络断开,点击树洞秘密,课程格子会因为无法从网络上刷新数据而崩溃掉.今天借解决此bug的为例,浅谈android的网络框架.

  2. 浅谈汽车车载导航仪GPS地图安装配置常见错误的解决方法(如提示缺少Style.ini等)

    如今汽车GPS导航仪产品已经非常成熟了,根据功能的多少价钱基本在600-2800元之间,一般而言,家庭买一款800元左右的导航仪已经足够用了. 现在以中关村最常见的e道航为例,简要谈一谈GPS外置SD ...

  3. 网络推广计划浅谈新站在前期收录少的原因及解决方法!

    网站在前期而言,被SEO蜘蛛抓取的频次很少的话有时候也让网络推广计划优化人员很捉急,想要让我们想要的内容被百度抓取并给予权重就需要合理的调配网站权重分配,那么网站新站需要如何分配站内资源呢?怎样分配才 ...

  4. 浅谈Android Architecture Components

    浅谈Android Architecture Components 浅谈Android Architecture Components 简介 Android Architecture Componen ...

  5. 浅谈Android保护技术__代码混淆

    浅谈Android保护技术__代码混淆 浅谈Android保护技术__代码混淆 代码混淆 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读 ...

  6. android 存储空间监控,浅谈 Android 内存监控(中)

    前言 在上篇 浅谈 Android 内存监控(上) 中,我们聊了 LeakCanary,微信的 Matirx 和美团的 Probe,它们各自有不同的应用场景,例如,在开发测试环境,我们会偏向用 Lea ...

  7. 浅谈Android中的MVP与动态代理的结合

    浅谈Android中的MVP与动态代理的结合 本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在Android开发平台上接触MVP足足算起来大概已经有一个年头左右.从最开始到现在经 ...

  8. 浅谈Android SDK开发

    目录 浅谈Android SDK开发 SDK开发的原则 SDK设计 功能与职责边界设计 接口设计 兼容性设计 发布输出设计 SDK文档设计 SDK项目架构 组件化.模块化 统一资源管理 第三方依赖管理 ...

  9. 浅谈Android引用计数(2)

    在浅谈Android引用计数(1)中讲了LightRefBase实现对象计数管理的原理,这篇文章将要分析重量级的引用基类:RefBase的实现和它的作用. 下面是RefBase和相关类的类图: 图中可 ...

最新文章

  1. 小程序 video 控制器外观调整_「小程序JAVA实战」小程序视频组件与api介绍(51)...
  2. c#基类 常用数据验证的封装,数字,字符,邮箱的验证
  3. java实现apriori算法_七大经典、常用排序算法的原理、Java 实现以及算法分析
  4. leetcode 1600. 皇位继承顺序(dfs)
  5. 组策略系列之四:《精典放送:组策略管理20点》
  6. SDOI2017R2PKUSC2017
  7. java小球反弹_java实现小球碰撞反弹(示例代码)
  8. Android精仿淘宝/QQ空间标题栏渐变效果
  9. 世界上最伟大的巫师「咪蒙」
  10. 导航recovery机制
  11. 真的精采!AI赢了DOTA界的世界冠军 让人兴奋又纠结
  12. 基于JAVA健康生活网站计算机毕业设计源码+系统+mysql数据库+lw文档+部署
  13. 登录验证,如果输入错误次数超过3次,则锁定该账户
  14. 小程序笔记 -- 封装函数
  15. css连接html的方式
  16. adm浏览器识别为linux,QQ浏览器Linux版qqbrowserlinux_1.0.0-1_amd64.deb能正常使用
  17. uni-icons中添加自定义图标
  18. 数据泵expdp/impdp导入导出详细说明
  19. django前后端结合_django前后端交互
  20. php 中如何设置单元格跨行,HTML表格中单元格跨行跨列

热门文章

  1. redis cli 删除key 模糊_redis 常用函数
  2. python连接oracle批量写入_oracle大数据量python导入实践-1w/s
  3. 电脑编程教学_“人工智能”将无处不在,我的孩子要不要学习电脑编程?
  4. AD域中NTP服务器的配置
  5. Linux内核调试 - 一般人儿我都不告诉他(一)【转】
  6. 解决maven官方库中没有oracle jdbc驱动问题 编辑
  7. ZendStudio导入一个已有的网站
  8. 国航移动门户让我出行无忧
  9. 《windows中GSX的管理》之四——cmware-cmd实例
  10. C#递归获取JSON所有键值对