前言:

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. 利用 istio 来对运行在 Kubernetes 上的微服务进行管理

    尝试在一个准生产环境下,利用 istio 来对运行在 Kubernetes 上的微服务进行管理. 这一篇是第一篇,将一些主要的坑和环境准备工作. 内容较多,因此无法写成手把手教程,希望读者有一定 Ku ...

  2. HDU 5071 模拟

    考察英语的题 - -# 按条件模拟,一遍即可了,每一个聊天对象有其价值U.数组模拟队列过程即可,若存在Top标记,则和Top标记的人聊天,否则和队列的第一个人聊天 mark记录队尾,top记录Top操 ...

  3. flask的使用(一)

    1.程序基本的说明 #-*-encoding=utf--*- 从flask中引入类 from flask import Flask ,render_template import config 初始化 ...

  4. RTC时钟和BKP的配置stm32

    摘自:https://blog.csdn.net/gtkknd/article/details/52233605 RTC和后备寄存器通过一个开关供电,在VDD有效的时候选择VDD供电,否则选择VBAT ...

  5. Ansible 部署

    环境: vim /etc/hosts 192.168.199.61 Ansible 192.168.199.60 Nginx1192.168.199.62 Nginx2192.168.199.63 H ...

  6. Snail—Hibernate各种异常

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXExNzkxNDIyMDE4/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  7. Nginx和Nginx+的比較(下)

    Nginx和Nginx+的比較(下) 作者:chszs.未经博主同意不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs 内容紧接上一篇<Nginx和 ...

  8. js进阶课程 12-9 jquery的事件对象event的方法有哪些?

    js进阶课程 12-9 jquery的事件对象event的方法有哪些? 一.总结 一句话总结:三组六个,阻止默认事件一组,阻止冒泡一组,阻止冒泡和剩余事件一组. 1.事件的默认动作指什么? 比如点a标 ...

  9. 算法 Tricks(六)— if 条件分支的简化

    考虑下面的三分支的定义式: f=⎧⎩⎨⎪⎪a,b,a+b,x>yx<yx=y int f = 0; if (x >= y) f += a; if (x <= y) f += b ...

  10. 3、Pycharm使用

    1.设置文件模板 file->settings->Editor->File and Code Templates->Python Script 2.运行 a.点击要运行的文件, ...