Fragment的狀態儲存startActivityForResult是哪個類的方法,在什麼情況下使用?
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方法。