写点什么

Fragment 中调用 startActivityForResult 的那些坑,安卓面试题目 2019

用户头像
Android架构
关注
发布于: 36 分钟前

int requestIndex = mNextCandidateRequestIndex;


//将 requestIndex 和 fragment 的 mWho 保存起来 mPendingFragmentActivityResults.put(requestIndex, fragment.mWho);mNextCandidateRequestIndex =(mNextCandidateRequestIndex + 1) % MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS;


return requestIndex;}


这里allocateRequestIndex方法就把requestIndex和 Fragment 的mWho变量关联起来了


在上面的`startActivityFromFra


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


gment方法中调用ActivityCompatstartActivityForResult方法发起启动Activity的时候又把requestIndexrequestCode`关联起来了


这样后面回调onActivityResult方法时就可以根据 requestCode 获取对应的 Fragment,以便调用 Fragment 的onActivityResult方法


最后看一下ActivityCompatstartActivityForResult方法


public static void startActivityForResult(@NonNull Activity activity, @NonNull Intent intent,int requestCode, @Nullable Bundle options) {if (Build.VERSION.SDK_INT >= 16) {activity.startActivityForResult(intent, requestCode, options);} else {activity.startActivityForResult(intent, requestCode);}}

(2)onActivityResult方法回调

通过断点调试的方法,我们会发现最先被回调的就是父 Activity 的onActivityResult,也就是我们的 FragmentActivity 的onActivityResult


@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {mFragments.noteStateNotSaved();int requestIndex = requestCode>>16;//requestIndex = 0 就表示没有 Fragment 发起过 startActivityForResult 调用 if (requestIndex != 0) {requestIndex--;


//根据 requestIndex 获取 Fragment 的 who 变量 String who = mPendingFragmentActivityResults.get(requestIndex);mPendingFragmentActivityResults.remove(requestIndex);if (who == null) {Log.w(TAG, "Activity result delivered for unknown Fragment.");return;}


//然后根据 who 变量获取目标 FragmentFragment targetFragment = mFragments.findFragmentByWho(who);if (targetFragment == null) {Log.w(TAG, "Activity result no fragment exists for who: " + who);} else {//最后调用 Fragment 的 onActivityResulttargetFragment.onActivityResult(requestCode & 0xffff, resultCode, data);}return;}


...super.onActivityResult(requestCode, resultCode, data);}


从上面的方法中可以看出 FragmentActivity 中的onActivityResult方法中对于 Fragment 的startActivityForResult调用已经做了处理。


这里就有一个问题需要注意了,我们一般都会覆写父 Activity 中的onActivityResult方法,这个时候我们必须在onActivityResult方法加上super.onActivityResult(),否则 Fragment 中的onActivityResult方法就没有办法回调到了。


这就是文章开头中提到的 2、3 两点需要注意的原因

getParentFragment 发起调用

这种情况一般发生在嵌套多层 Fragment 的时候


getParentFragment 发起调用的过程和上面的类似,只不过发起调用的是当前 Fragment 的父 Fragment,所以最后回调的也是父 Activity 的onActivityResult方法和父 Fragment 的onActivityResult方法。


所以如果想在子 Fragment 中监听到onActivityResult方法的回调,就不要用这种方式

getActivity 方法发起调用

这个就更简单了,直接调用的是父 Activity 的onActivityResult方法


//FragmentActivity.class@Overridepublic void startActivityForResult(Intent intent, int requestCode) {// If this was started from a Fragment we've already checked the upper 16 bits were not in// use, and then repurposed them for the Fragment's index.if (!mStartedActivityFromFragment) {if (requestCode != -1) {checkForValidRequestCode(requestCode);}}super.startActivityForResult(intent, requestCode);}


所以从源码也可以看出,这种方式最后不会回调 Fragment 的onActivityResult方法

总结

在 Fragment 中调用startActivityForResult以及监听onActivityResult是很常见的一种应用方式,但是稍不注意就会掉到坑里,比如因为ActivityonActivityResult方法没有调用super.onActivityResult()方法而导致 Fragment 中死活接收不到onActivityResult的回调。


最后总结一下几种场景的应用步骤:

(1)一个 Activity 嵌套一层 Fragment,Fragment 中需要监听 onActivityResult 返回结果
用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Fragment中调用startActivityForResult的那些坑,安卓面试题目2019