Fragment调用startActivityForResult ---> HostCallbacks . onStartActivityFromFragment ---> FragmentActivity . startActivityFromFragment
FragmentActivity的startActivityFromFragment方法
public void startActivityFromFragment(Fragment fragment, Intent intent,
int requestCode, @Nullable Bundle options) {
mStartedActivityFromFragment = true;
try {
if (requestCode == -1) {
ActivityCompat.startActivityForResult(this, intent, -1, options);
return;
}
checkForValidRequestCode(requestCode);
int requestIndex = allocateRequestIndex(fragment);
ActivityCompat.startActivityForResult(
this, intent, ((requestIndex + 1) << 16) + (requestCode & 0xffff), options);
} finally {
mStartedActivityFromFragment = false;
}
}
首先将FragmentActivity父类BaseFragmentActivityJB 的 mStartedActivityFromFragment 设置为 true;
然后根据requestCode的值判断,调用startActivity默认这里的requestCode 为 -1 ,如果调用startActivityForResult则不会走这步;
下一步通过checkForValidRequestCode会查验requestCode是否正确
static void checkForValidRequestCode(int requestCode) {
if ((requestCode & 0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
}
}
如果指定的requestCode大于65535,则会报异常.
下一步调用allocateRequestIndex方法得到请求队列中的索引
// Allocates the next available startActivityForResult request index.
private int allocateRequestIndex(Fragment fragment) {
// Sanity check that we havn't exhaused the request index space.
if (mPendingFragmentActivityResults.size() >= MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS) {
throw new IllegalStateException("Too many pending Fragment activity results.");
}
// Find an unallocated request index in the mPendingFragmentActivityResults map.
while (mPendingFragmentActivityResults.indexOfKey(mNextCandidateRequestIndex) >= 0) {
mNextCandidateRequestIndex =
(mNextCandidateRequestIndex + 1) % MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS;
}
int requestIndex = mNextCandidateRequestIndex;
mPendingFragmentActivityResults.put(requestIndex, fragment.mWho);
mNextCandidateRequestIndex =
(mNextCandidateRequestIndex + 1) % MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS;
return requestIndex;
}
如果队列中超过了65535-1 那么报参数错误,然后得到在等待获取结果的队列中的索引,indexOfKey >=0 代表已经存在了,只能将mNextCandidateRequestIndex+1;不存在则赋值给requestIndex 然后返回,并且将mNextCandidateRequestIndex+1 给下一个请求做准备.
下一步调用
ActivityCompat . startIntentSenderForResult(this, intent,((requestIndex + 1) << 16) + (requestCode & 0xffff), fillInIntent,flagsMask, flagsValues, extraFlags, options);
(requestIndex + 1) << 16 代表将请求的索引值左移16位,在较高16位中保存当前的索引值
requestCode & 0xffff 就是requestCode,为了屏蔽二进制位,置位0
public static void startIntentSenderForResult(Activity activity, IntentSender intent,
int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException {
if (Build.VERSION.SDK_INT >= 16) {
ActivityCompatJB.startIntentSenderForResult(activity, intent, requestCode, fillInIntent,
flagsMask, flagsValues, extraFlags, options);
} else {
activity.startIntentSenderForResult(intent, requestCode, fillInIntent, flagsMask,
flagsValues, extraFlags);
}
}
因此这里调用startIntentSenderForResult方法的参数requestCode实际上是 ((requestIndex + 1) << 16) + (requestCode & 0xffff ) 而不是之前的requestCode。
接着调用ActivityCompatJB . startIntentSenderForResult方法(这里只拿API>=16举例)
public static void startIntentSenderForResult(Activity activity, IntentSender intent,
int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
Bundle options) throws IntentSender.SendIntentException {
activity.startIntentSenderForResult(intent, requestCode, fillInIntent, flagsMask,
flagsValues, extraFlags, options);
}
最后调用Activity的 startIntentSenderForResult 方法,ActivityManagerNative.getDefault().startActivityIntentSender 真正启动一个Activity。
然后我们查看FragmentActivity中接收setResult的值的方法onActivityResult
/**
* Dispatch incoming result to the correct fragment.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mFragments.noteStateNotSaved();
int requestIndex = requestCode>>16;
if (requestIndex != 0) {
requestIndex--;
String who = mPendingFragmentActivityResults.get(requestIndex);
mPendingFragmentActivityResults.remove(requestIndex);
if (who == null) {
Log.w(TAG, "Activity result delivered for unknown Fragment.");
return;
}
Fragment targetFragment = mFragments.findFragmentByWho(who);
if (targetFragment == null) {
Log.w(TAG, "Activity result no fragment exists for who: " + who);
} else {
targetFragment.onActivityResult(requestCode & 0xffff, resultCode, data);
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
首先将requestCode值右移16位,得到他在等待处理Fragment数据队列的索引,由上面的 ActivityCompat . startIntentSenderForResult方法参数得知,requestCode是左移了16位,
那么这里就可以根据requestIndex的值判断是Fragment调用了startActivityForResult还是Activity,如果requestIndex不为0代表是Fragment触发,下面得到 targetFragment 然后可以通过targetFragment的onActivityResult方法得到返回值;如果requestIndex为0代表是Activity调用了startActivityForResult,那么直接返回的是Activity的onActivityResult方法。