前言:

Fragment也可以使用startActivityForResult方法去打开一个Activity,然后在其onActivityResult方法中处理结果,可是当Fragment嵌套的时候,由于FragmentActivity的BUG导致只会回调最外那层Fragment的onActivityResult方法,于是乎当前Fragment就收不到结果了。

BUG分析:

解决这个问题之前我们先通过源码分析一下是什么原因导致的,以22.2.1版本的support-v4库为例

我们先从Fragment的startActivityForResult开始分析

public void startActivityForResult(Intent intent, int requestCode) {
if(this.mActivity == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
} else {
this.mActivity.startActivityFromFragment(this, intent, requestCode);
}
}

很明显直接调用了FragmentActivity的startActivityForFragment方法

public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) {
if(requestCode == -1) {
super.startActivityForResult(intent, -1);
} else if((requestCode & -65536) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
} else {
super.startActivityForResult(intent, (fragment.mIndex + 1 << 16) + (requestCode & '\uffff'));
}
}

在这里将requestCode和Fragment的mIndex融合成了一个整型作为新的requestCode,那么新的requestCode的高16位表示Fragment的索引,低16为表示原本的requestCode,看来这里是用Fragment的mIndex作为查找依据的

接下来再看FragmentActivity的onActivityResult方法

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()) {
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 & '\uffff', resultCode, data);
} } else {
Log.w("FragmentActivity", "Activity result fragment index out of range: 0x" + Integer.toHexString(requestCode));
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}

在这里取出requestCode的高16位,不等0就是子Fragment的mIndex,但是接下来却直接从Activity的Fragment列表中根据索引去找Fragment,如果你的Fragment是被子Fragment的childFragmentManager管理的话这样是绝对找不到的,于是乎答案很明了了。

解决问题:

解决这个问题的办法有两个

第一个是直接升级support-v4到23.2.0以上的版本,因为23.2.0以上就修复了这个BUG,具体怎么解决的就不再赘述了有兴趣的可自行研究,但由于种种原因没办法升级23.2.0的还大有人在

第二种办法就是自己动手丰衣足食,在Fragment层重写相关方法解决问题

接下来着重介绍自己动手丰衣足食的办法,完整实现如下:

public class ForResultNestedCompatFragment extends Fragment {
private ForResultNestedCompatFragment forResultChildFragment; @Override
public void startActivityForResult(Intent intent, int requestCode) {
Fragment parentFragment = getParentFragment();
if (parentFragment != null && parentFragment instanceof ForResultNestedCompatFragment) {
((ForResultNestedCompatFragment) parentFragment).startActivityForResultFromChildFragment(intent, requestCode, this);
} else {
forResultChildFragment = null;
super.startActivityForResult(intent, requestCode);
}
} private void startActivityForResultFromChildFragment(Intent intent, int requestCode, ForResultNestedCompatFragment childFragment) {
forResultChildFragment = childFragment; Fragment parentFragment = getParentFragment();
if (parentFragment != null && parentFragment instanceof ForResultNestedCompatFragment) {
((ForResultNestedCompatFragment) parentFragment).startActivityForResultFromChildFragment(intent, requestCode, this);
} else {
super.startActivityForResult(intent, requestCode);
}
} @Override
public final void onActivityResult(int requestCode, int resultCode, Intent data) {
if (forResultChildFragment != null) {
forResultChildFragment.onActivityResult(requestCode, resultCode, data);
forResultChildFragment = null;
} else {
onActivityResultNestedCompat(requestCode, resultCode, data);
}
} public void onActivityResultNestedCompat(int requestCode, int resultCode, Intent data) { }
}

具体思路一句话概括就是startActivityForResult的时候一层一层晚上让父Fragment持有子Fragment的引用,回调onActivityResult的时候父Fragment再一层一层传给子Fragment

具体用法就是让所有的Fragment都继承ForResultNestedCompatFragment,然后用onActivityResultNestedCompat方法替换onActivityResult方法

Android解决Fragment多层嵌套时onActivityResult无法正确回调的问题的更多相关文章

  1. [Android Pro] fragment中嵌套viewpager,vierpager中有多个fragment,不显示

    referece to :  http://blog.csdn.net/mybook1122/article/details/24003343 现在好多应用流行一种布局.底部几个工具栏选项,上面也有类 ...

  2. android 解决ViewPager双层嵌套的滑动问题

    解决ViewPager双层嵌套的滑动问题 今天我分享一下ViewPager的双层嵌套时影响内部ViewPager的触摸滑动问题 之前在做自己的一个项目的时候,遇到广告栏图片动态切换,我第一时间想到的就 ...

  3. Bootstrap中模态框多层嵌套时滚动条问题

    在使用Bootstrap中模态框过程中,如果出现多层嵌套的时候,如打开模态框A,然后在A中打开模态框B,在关闭B之后,如果A的内容比较多,滚动条会消失,而变为Body的滚动条,这是由于模态框自带的遮罩 ...

  4. Android 解决ScrollView下嵌套ListView进页面不在顶部的问题

    以下为整理: 方法1 刚开始还可以,后来再调试时就不行了. 为了解决scrollview和listview冲突  设置了listview的高度   结果进页面就不是在顶部了 . 解决方案1:Scrol ...

  5. vue中,对象数组多层嵌套时,更新数据更新页面

    vue中的对象和数组的元素直接赋值修改时,是不能响应到view中去的 1.对象更新 this.a={title:'列表1’}; this.a.title='列表2’; <h1>{{a.ti ...

  6. 问题集录--Android:解决Studio新建项目时,在 Building gradle project info 一直卡住

    Android Studio导入项目的时候,一直卡在Building gradle project info这一步,主要原因还是因为被墙的结果.gradle官网虽然可以访问,但是速度连蜗牛都赶不上.. ...

  7. iframe多层嵌套时,Jquery获取元素

    在项目中,尤其是后台管理项目,会使用到iframe嵌套的网页,说起iframe,真的是个让人头疼的东西,能避开是最好避开.不然要请随身备好氧气瓶哈(因为管理和调试过程中往往会被气缺氧!!!哈哈哈~~~ ...

  8. iframe多层嵌套时获取元素总结

    父页面获取子页面元素: 注意:onload事件 jQuery获取: $("iframe").contents().find("holder")......; ( ...

  9. 2014-10-28——iframe多层嵌套时获取元素总结

    同域: 父页面获取子页面元素: 注意:onload事件 jQuery获取:$("iframe").contents().find("holder")...... ...

随机推荐

  1. Android开发工具之adt-bundle-windows

    adt-bundle-windows是非常久之前的android开发工具.是集成了ADT版本号的eclipse,可是里面并没有下载SDK.这个须要自己单独下载,这个工具适合刚開始学习的人使用. 由于刚 ...

  2. 5. Node基础编程

      基于Chrome V8引擎 单线程 使用JavaScript开发后端代码 非阻塞的IO common规范 common一定是通过module.exports={}输出 创建Http Server ...

  3. 利用mysql5.6 的st_distance 实现按照距离远近排序。 (转载)

    http://blog.csdn.net/zhouzhiwengang/article/details/53612481

  4. ab压测返回结果解析

    Server Software:        Apache/2.2.25 (服务器软件名称及版本信息)Server Hostname:        localhost (服务器主机名)Server ...

  5. nokia 5220 XpressMusic 自己刷机

    看了半天各种论坛,是在不知道从哪里下手,所以自己写一篇自己刷机的新的.凤凰那个软件好像已经挂了,每次打开就是service is not authorized. 所以还是使用nokia自己的官方下载平 ...

  6. 硬件——STM32 , SN74HC573锁存器

    74HC573是一款高速CMOS器件: 上图中:输出使能为:OE   锁存使能为:LE 典型电路: 上图中:PWR-AL-0,PWR-AL-1,PWR-AL-2:是单片机输出的高低电平给573 对应的 ...

  7. P2P平台公司的9种职位

     1.技术   开发类:开发系统,实现新功能   维护类:服务器和网站维护   更多:Web前端等      观点:技术岗位很关键,但是很多不懂技术的老板,不会认可你的价值.   太多的老板,以为技术 ...

  8. 字符的输入和输出即:getchar和putchar

    #include <stdio.h> int main(int argc, const char * argv[]) { putchar(getchar());//这种方式就是输入一个字符 ...

  9. 公钥,私钥和数字签名这样最好理解 分类: B3_LINUX 2015-05-06 16:25 59人阅读 评论(0) 收藏

    一.公钥加密 假设一下,我找了两个数字,一个是1,一个是2.我喜欢2这个数字,就保留起来,不告诉你们(私钥),然后我告诉大家,1是我的公钥. 我有一个文件,不能让别人看,我就用1加密了.别人找到了这个 ...

  10. Coverage报告生成

    Coverage报告生成 覆盖率 覆盖率驱动的验证方法中覆盖率报告的生成至关重要,现在介绍一下使用DVE和URG生成覆盖率报告的步骤. 使用VCS生成数据 在VCS的运行脚本中添加-cm cond+f ...