Fragment之onActivityResult
来源:互联网 发布:手机连不上4g网络 编辑:程序博客网 时间:2024/05/22 01:42
Fragment之onActivityResult
我们都知道Activity下执行startActivityForResult 然后在onActivityResult函数中处理带回的结果,那么fragment中执行startActivityForResult而后其onActivityResult是否能够正确的被调用呢?
下图是实际调用的时序图:
Fragment->Fragment:startActivityForResult
Fragment->HostCallbacks:onStartActivityFromFragment
HostCallbacks->FragmentActivity:startActivityFromFragment
FragmentActivity->Fragment:onActivityResult
fragment执行startActivityForResult最终执行的是FragmentActivity的startActivityFromFragment函数,其中,新requestCode是根据fragment的index(高16位) + 原requestCode(低16位) 被重新计算的。
public void startActivityFromFragment(Fragment fragment, Intent intent,int requestCode) { if (requestCode == -1) { super.startActivityForResult(intent, -1); return; } if ((requestCode&0xffff0000) != 0) { throw new IllegalArgumentException("Can only use lower 16 bits for requestCode"); } super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff)); }
实际接受Result的还是Activity,Activity先会看看requestCode是不是由其fragment发出的(判断高16位是否有内容),如果是,则根据requestCode中解析得到index找到对应的fragment,并还原原requestCode(取低16位) ,最后调用fragmento的nActivityResult。
注:mActive是存放Fragment实例的队列,而mIndex则是某fragment在mActive中的序号
protected void onActivityResult(int requestCode, int resultCode, Intent data) { mFragments.noteStateNotSaved(); int index = requestCode>>16; if (index != 0) { index--; final int activeFragmentsCount = mFragments.getActiveFragmentsCount(); if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount) { Log.w(TAG, "Activity result fragment index out of range: 0x" + Integer.toHexString(requestCode)); return; } final List<Fragment> activeFragments = mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount)); Fragment frag = activeFragments.get(index); if (frag == null) { Log.w(TAG, "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.java下。
public void onActivityResult(int requestCode, int resultCode, Intent data) {}
发现这是个空函数,这意味着,
* Activity下的Fragment的onActivityResult是可以接收到Result.
* Fragment下的Fragment默认无法收到onActivityResult的结果的。要做到也可以,但自己需要实现规则。
Fragment下的Fragment 是无法收到Result,如何应对?
但是Fragment的嵌套使用并不少见,举例来说:Fragment A下使用到FragmentDialog B 及 FragmentDialog C 或更多,在B,C 使用场合中都会启动电话本,并且通过onActivityResult返回选择结果,那么在Result通过onActivityResult流入到A,那么A根据什么来判断 最后的结果是流向 B 还是C .
[*]–>FragmentActivity
FragmentActivity–>Fragment_A
Fragment_A–>Fragment_B
Fragment_A–>Fragment_C
Fragment_A:第一层级fragment
Fragment_B:startActivityResult()
Fragment_B:第二层级fragment
Fragment_C:startActivityResult()
Fragment_C:第二层级fragment
我的解决方案:
那还是借鉴系统的办法,系统将16~31位来存储区分FragmentActivity第一层级fragment的index,而0~15位存储实际的requestCode.而我为了区分第二层级的fragment,将第8~15位用来存储fragment的id号,将第0~7位用来存储实际的requestCode. 限制:需要定义的requestCode小于256
建立一个工具类
用来在第一层级fragment里进行requestCode的截获封装(对应startActivityForResult())及解析(对应onActivityResult())
public class FragmentForActivityResultHelper { public static final String CHILD_FRAGMENT_TAG = "child_fragment_tag"; /** * 和childFragmentTag一一对应的id,不得大于0xff. */ private int childFragmentIndex = 0; /** * key是childFragmentIndex,值是childFragmentTag */ private HashMap<Integer, String> childFragmentTagMap = new HashMap<>(); public void startActivityForResult(Intent intent, int requestCode, @NonNull Fragment fragment_) { Bundle b = intent.getExtras(); String childFragmentTag; if (b != null) { childFragmentTag = (String) b.get(CHILD_FRAGMENT_TAG); if (childFragmentTag != null) { requestCode = getNewRequestCode(requestCode, childFragmentTag); } } fragment_.getActivity().startActivityForResult(intent, requestCode); } private synchronized int getNewRequestCode(int requestCode, String childFragmentTag) { if ((requestCode & 0xff00) != 0) { throw new IllegalArgumentException("Can only use lower 8 bits for requestCode"); } childFragmentIndex++; if (childFragmentIndex >= 0xff) { childFragmentIndex = 0; } int newRequestCode = ((childFragmentIndex << 8) + (requestCode & 0xff)); childFragmentTagMap.put(newRequestCode, childFragmentTag); return newRequestCode; } /** * @return ture:说明该Result已经被处理了。 false:没有处理。 */ public boolean onActivityResult(int requestCode, int resultCode, Intent data, Fragment fragment_) { if ((requestCode & 0xff00) != 0) { int key = requestCode & 0xffff; String tag = childFragmentTagMap.get(key); if (tag != null) { childFragmentTagMap.remove(key); Fragment fragment = fragment_.getChildFragmentManager().findFragmentByTag(tag); if (fragment != null) { fragment.onActivityResult(requestCode & 0xff, resultCode, data); return true; } } } return false; }}
在第一层级Fragment中如何使用
“`
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(fragmentForActivityResultHelper.onActivityResult(requestCode,resultCode,data,this)) {
return;
}
/**在FragmentForActivityResultHelper对象没有处理ActivityResult的时候,这里进行其他requestCode的处理**/
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
fragmentForActivityResultHelper.startActivityForResult(intent,requestCode,this);
}
###在第二层级Fragment中如何使用
public void startActivityForResult(Intent intent, int requestCode) {
Fragment pf = getParentFragment();
intent.putExtra(FragmentForActivityResultHelper.CHILD_FRAGMENT_TAG, SHOPPING_ADDRESS_LIST);
if (pf != null) {
pf.startActivityForResult(intent, requestCode);
return;
}
Activity a = getActivity();if (a != null) { a.startActivityForResult(intent, requestCode);}
}
“`
适用场景
上面这样做的原因主要针对的场合是:
有两层fragment,并且有至少两个第二层级的fragment需要处理有相同requestCode的ActivityResult
周边影响:
场景1:有两层fragment,第二层级的fragment间没有处理相同requestCode的ActivityResult,
那么FragmentForActivityResultHelper其实根本用不上,只需要根据requestCode的值就能区分该将数据传给哪个fragment.
那如果只有其中一个使用了FragmentForActivityResultHelper而其他没有会有什么问题吗?不会。
场景2:只有一层fragment
这个问题就根本不存在。
场景3:
- Fragment之onActivityResult
- fragment onActivityResult
- Fragment onActivityResult
- Fragment系列之嵌套导致错乱的onActivityResult数据传递
- fragment不响应onActivityResult
- Android fragment onActivityResult 问题
- Fragment 不响应onActivityResult
- Fragment中的OnActivityResult(...)
- Fragment Activity onActivityResult
- Android fragment onActivityResult 不起作用
- Android fragment onActivityResult 问题
- Fragment中响应onActivityResult
- fragment 的onActivityResult
- Android fragment onActivityResult 问题
- Fragment onActivityResult问题
- fragment 不调用 onActivityResult
- Fragment 不响应onActivityResult
- Fragment onActivityResult方法问题
- AndroidStudio初体验
- mybatis学习笔记(2)-mybatis概述
- 11.2 RAC: In "crsctl stat res -t" State Details May Be Missing or Incorrect (文档 ID 1086563.1)
- Spring之ApplicationContext
- RF射频通信
- Fragment之onActivityResult
- mysql主从复制 设置中继日志自动清除 主从同步失败,如何快速同步
- mybatis学习笔记(3)-入门程序一
- Demo9:简单晒单效果
- mybatis学习笔记(3)-入门程序二
- Java设计模式---单例模式
- LeetCode88——Merge Sorted Array
- AAC音频格式详解
- BZOJ-3231 递归数列 矩阵连乘+快速幂