前言:

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. spring+mybatis+Atomikos JTA事务配置说明

    一.概览 Atomikos是一个公司名字,旗下最著名的莫过于其Atomikos的事务管理器产品.产品分两个:一个是开源的TransactionEssentials,一个是商业的ExtremeTrans ...

  2. ORA-01078错误举例:SID的大写和小写错误

    案例重演: dbca建库.SID:metro    --手工建库时实例名小写的metro ...... [oracle@org54 ~]$ export ORACLE_SID=METRO        ...

  3. x264代码剖析(三):主函数main()、解析函数parse()与编码函数encode()

    x264代码剖析(三):主函数main().解析函数parse()与编码函数encode() x264的入口函数为main().main()函数首先调用parse()解析输入的參数,然后调用encod ...

  4. mycat 之datanode datahost writehost readhost 区别(转)

    <?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> &l ...

  5. cpu信息

    在linux系统下能够通过cat /proc/cpuinfo来查看本机上cpu的相关信息,通过processor能够推断逻辑cpu的个数,physical id能够推断物理cpu的个数,通过cpu c ...

  6. C#利用反射机制,获取实例的属性和属性值

    C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值 对应某个类的实例化的对象tc, 遍历获取所有属性(子成员)的方法(采用反射): Type t = tc.GetType();// ...

  7. 不可摸数 【杭电-HDOJ-1999】 附题

    /* hdu 1999 不可摸数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  8. php课程 1-3 web项目中php、html、js代码的执行顺序是怎样的(详解)

    php课程 1-3 web项目中php.html.js代码的执行顺序是怎样的(详解) 一.总结 一句话总结:b/s结构 总是先执行服务器端的先.js是客户端脚本 ,是最后执行的.所以肯定是php先执行 ...

  9. windows ffmpeg 的安装

    本文我们要安装的是 windows 下的 ffmpeg 命令行工具,安装的步骤十分简单,分为:下载.解压.配置环境变量. 下载,进入 http://ffmpeg.org/download.html#b ...

  10. 数据结构与算法实验题 9.1 K 歌 DFS+剪枝

    数据结构与算法实验题 K 歌 ★实验任务 3* n 个人(标号1~ 3 * n )分成 n 组 K 歌.有 m 个 3 人组合,每个组合都对应一个分数,你能算出最大能够得到的总分数么? ★数据输入 输 ...