主要分析startActivityForResult以后Fragment中onActivityResult回调回来的逻辑
android.app.Fragment 类中有这么一个方法,这里会去调用mHost中的onStartActivityFromFragment,所以这里来看看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 类中有这么一个Callback,这个Callback是android.app.FragmentHostCallback的一个实例,从这个类的注释中看到,Fragment肯定是有宿主的,正如Activity中去开启一个Fragment,这个Activity就是Fragment的宿主了,这个Callback就是用来回调宿主中的一些方法的。
// Activity this fragment is attached to.
FragmentHostCallback mHost;
看这个android.app.FragmentHostCallback的一个方法,最终会调用startActivity,这个很明显就是Activity中的方法,所以确定了这个类的作用以后,会更加的清晰我们继续分析下去的流程。
/**
* 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);
}
其实上面的方法不是真正的执行流程, Activity中有HostCallbacks这个东西里面重写了上面onStartActivityFromFragment方法
class HostCallbacks extends FragmentHostCallback<Activity> {
public HostCallbacks() {
super(Activity.this /*activity*/);
}
...省略一些不必要的方法
@Override
public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
Bundle options) {
//这里就是重写了的方法,重点分析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);
}