主要分析startActivityForResult以后Fragment中onActivityResult回調(diào)回來(lái)的邏輯
android.app.Fragment 類(lèi)中有這么一個(gè)方法,這里會(huì)去調(diào)用mHost中的onStartActivityFromFragment救鲤,所以這里來(lái)看看mHost是什么鬼久窟?
/**
* Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment's
* containing Activity.
*/
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
mHost.onStartActivityFromFragment(this, intent, requestCode, options);
}
android.app.Fragment 類(lèi)中有這么一個(gè)Callback,這個(gè)Callback是android.app.FragmentHostCallback的一個(gè)實(shí)例蜒简,從這個(gè)類(lèi)的注釋中看到瘸羡,F(xiàn)ragment肯定是有宿主的,正如Activity中去開(kāi)啟一個(gè)Fragment搓茬,這個(gè)Activity就是Fragment的宿主了,這個(gè)Callback就是用來(lái)回調(diào)宿主中的一些方法的队他。
// Activity this fragment is attached to.
FragmentHostCallback mHost;
看這個(gè)android.app.FragmentHostCallback的一個(gè)方法卷仑,最終會(huì)調(diào)用startActivity,這個(gè)很明顯就是Activity中的方法麸折,所以確定了這個(gè)類(lèi)的作用以后锡凝,會(huì)更加的清晰我們繼續(xù)分析下去的流程。
/**
* Starts a new {@link Activity} from the given fragment.
* See {@link Activity#startActivityForResult(Intent, int)}.
*/
public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
Bundle options) {
if (requestCode != -1) {
throw new IllegalStateException(
"Starting activity with a requestCode requires a FragmentActivity host");
}
mContext.startActivity(intent);
}
其實(shí)上面的方法不是真正的執(zhí)行流程垢啼, Activity中有HostCallbacks這個(gè)東西里面重寫(xiě)了上面onStartActivityFromFragment方法
class HostCallbacks extends FragmentHostCallback<Activity> {
public HostCallbacks() {
super(Activity.this /*activity*/);
}
...省略一些不必要的方法
@Override
public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
Bundle options) {
//這里就是重寫(xiě)了的方法窜锯,重點(diǎn)分析startActivityFromFragment
Activity.this.startActivityFromFragment(fragment, intent, requestCode, options);
}
...省略一些不必要的方法
下面就是startActivityFromFragment的主要邏輯
/**
* This is called when a Fragment in this activity calls its
* {@link Fragment#startActivity} or {@link Fragment#startActivityForResult}
* method.
*
* <p>This method throws {@link android.content.ActivityNotFoundException}
* if there was no Activity found to run the given Intent.
*
* @param fragment The fragment making the call.
* @param intent The intent to start.
* @param requestCode Reply request code. < 0 if reply is not requested.
* @param options Additional options for how the Activity should be started.
* See {@link android.content.Context#startActivity(Intent, Bundle)
* Context.startActivity(Intent, Bundle)} for more details.
*
* @throws android.content.ActivityNotFoundException
*
* @see Fragment#startActivity
* @see Fragment#startActivityForResult
*/
public void startActivityFromFragment(@NonNull Fragment fragment,
@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
startActivityForResult(fragment.mWho, intent, requestCode, options);
}
/**
* @hide
*/
@Override
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
Uri referrer = onProvideReferrer();
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, who, requestCode,
ar.getResultCode(), ar.getResultData());
}
cancelInputsAndStartExitTransition(options);
}