針對上篇《過時(shí)的OnActivityResult一》厚棵,本篇進(jìn)行源碼解析:
先來看一下在Activity中啟動launcher之后是怎么實(shí)現(xiàn)這種功能的
調(diào)用ComponentActivity中的registerForActivityResult,該方法返回一個(gè)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,調(diào)用了ActivityResultRegistry中的register
register則使用了lifecycleOwner實(shí)現(xiàn)了自動解綁功能愈污,然后返回了一個(gè)ActivityResultLauncher,并調(diào)用了invoke方法
public final <I, O> ActivityResultLauncher<I> register() {
// 注冊一個(gè)requestCode并保存回調(diào),這里的回調(diào)就是在onActivityResult攔截的時(shí)候取的
final int requestCode = registerKey(key);
mKeyToCallback.put(key, new CallbackAndContract<>(callback, contract));
// 這里最終返回的是我們需要的ActivityResultLauncher怠惶,并調(diào)用了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);
}
};
}
這個(gè)時(shí)候回到ComponentActivity的mActivityResultRegistry看下源碼就知道是怎么一回事了涨缚,該方法先判斷了action是否為權(quán)限或者支付,最后調(diào)用的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 權(quán)限處理
} else if (ACTION_INTENT_SENDER_REQUEST.equals(intent.getAction())) {
//google支付
} else {
// 啟動activity最終調(diào)用的是這里
ActivityCompat.startActivityForResult(activity, intent, requestCode, options != null ? options.toBundle() : null);
}
}
};
具體流程大概是這個(gè)樣子策治,再來看下是如何攔截onActivityResult的
ActivityResultRegistry攔截了onActivityResult,onRequestPermissionsResult同理脓魏,dispatchResult方法判斷了是否需要攔截,根據(jù)在調(diào)用register的時(shí)候保存的registerkey來判斷
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
//處理onActivityResult如果不是launcher啟動的則還是走onActivityResult
//不過這里已經(jīng)標(biāo)記為過時(shí)
if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
然后拿出mKeyToCallback中保存對應(yīng)requestCode的回調(diào)ActivityResultCallback,這個(gè)時(shí)候調(diào)用ActivityResultCallback的onActivityResult通惫,這樣就能拿到對應(yīng)的數(shù)據(jù)和狀態(tài)
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;
}
//這里就比較簡單了,獲取回調(diào)之后返回parseResult生成的類數(shù)據(jù)
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);
}