Fragment 中调用 startActivityForResult 的那些坑,安卓面试题目 2019
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
gment方法中调用
ActivityCompat的
startActivityForResult方法发起启动Activity的时候又把
requestIndex和
requestCode`关联起来了
这样后面回调onActivityResult
方法时就可以根据 requestCode 获取对应的 Fragment,以便调用 Fragment 的onActivityResult
方法
最后看一下ActivityCompat
的startActivityForResult
方法
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
是很常见的一种应用方式,但是稍不注意就会掉到坑里,比如因为Activity
的onActivityResult
方法没有调用super.onActivityResult()
方法而导致 Fragment 中死活接收不到onActivityResult
的回调。
最后总结一下几种场景的应用步骤:
评论