针对上篇《过时的OnActivityResult一》,本篇进行源码解析:
先来看一下在Activity中启动launcher之后是怎么实现这种功能的
调用ComponentActivity中的registerForActivityResult,该方法返回一个ActivityResultLauncher用于启动Intent
public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
@NonNull final ActivityResultContract<I, O> contract,
@NonNull final ActivityResultRegistry registry,
@NonNull final ActivityResultCallback<O> callback) {
return registry.register(
"activity_rq#" + mNextLocalRequestCode.getAndIncrement(), this, contract, callback);
}
由于没有自定义ActivityResultRegistry,所以这里使用的是ComponentActivity中的mActivityResultRegistry,调用了ActivityResultRegistry中的register
register则使用了lifecycleOwner实现了自动解绑功能,然后返回了一个ActivityResultLauncher,并调用了invoke方法
public final <I, O> ActivityResultLauncher<I> register() {
// 注册一个requestCode并保存回调,这里的回调就是在onActivityResult拦截的时候取的
final int requestCode = registerKey(key);
mKeyToCallback.put(key, new CallbackAndContract<>(callback, contract));
// 这里最终返回的是我们需要的ActivityResultLauncher,并调用了ComponentActivity中mActivityResultRegistry的invoke
return new ActivityResultLauncher<I>() {
@Override
public void launch(I input, @Nullable ActivityOptionsCompat options) {
invoke(requestCode, contract, input, options);
}
@Override
public void unregister() {
ActivityResultRegistry.this.unregister(key);
}
};
}
这个时候回到ComponentActivity的mActivityResultRegistry看下源码就知道是怎么一回事了,该方法先判断了action是否为权限或者支付,最后调用的startActivityForResult
private ActivityResultRegistry mActivityResultRegistry = new ActivityResultRegistry() {
@Override
public <I, O> void invoke() {
ComponentActivity activity = ComponentActivity.this;
Intent intent = contract.createIntent(activity, input);
if (ACTION_REQUEST_PERMISSIONS.equals(intent.getAction())) {
// requestPermissions path 权限处理
} else if (ACTION_INTENT_SENDER_REQUEST.equals(intent.getAction())) {
//google支付
} else {
// 启动activity最终调用的是这里
ActivityCompat.startActivityForResult(activity, intent, requestCode, options != null ? options.toBundle() : null);
}
}
};
具体流程大概是这个样子,再来看下是如何拦截onActivityResult的
ActivityResultRegistry拦截了onActivityResult,onRequestPermissionsResult同理,dispatchResult方法判断了是否需要拦截,根据在调用register的时候保存的registerkey来判断
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
//处理onActivityResult如果不是launcher启动的则还是走onActivityResult
//不过这里已经标记为过时
if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
然后拿出mKeyToCallback中保存对应requestCode的回调ActivityResultCallback,这个时候调用ActivityResultCallback的onActivityResult,这样就能拿到对应的数据和状态
public final boolean dispatchResult(int requestCode, int resultCode, @Nullable Intent data) {
String key = mRcToKey.get(requestCode);
if (key == null) {
//使用的startActivityForResult
return false;
}
doDispatch(key, resultCode, data, mKeyToCallback.get(key));
return true;
}
//这里就比较简单了,获取回调之后返回parseResult生成的类数据
private <O> void doDispatch(String key, int resultCode, @Nullable Intent data, @Nullable CallbackAndContract<O> callbackAndContract) {
if (callbackAndContract != null && callbackAndContract.mCallback != null) {
ActivityResultCallback<O> callback = callbackAndContract.mCallback;
ActivityResultContract<?, O> contract = callbackAndContract.mContract;
//parseResult返回的什么这里就获取的什么
callback.onActivityResult(contract.parseResult(resultCode, data));
} else {
mPendingResults.putParcelable(key, new ActivityResult(resultCode, data));
}
}
fragment也是先拿到mActivityResultRegistry然后还是走的Activity流程
public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
@NonNull final ActivityResultContract<I, O> contract,
@NonNull final ActivityResultCallback<O> callback) {
return prepareCallInternal(contract, new Function<Void, ActivityResultRegistry>() {
@Override
public ActivityResultRegistry apply(Void input) {
//返回了ComponentActivity的ActivityResultRegistry
if (mHost instanceof ActivityResultRegistryOwner) {
return ((ActivityResultRegistryOwner) mHost).getActivityResultRegistry();
}
return requireActivity().getActivityResultRegistry();
}
}, callback);
}
网友评论