美文网首页
过时的OnActivityResult(二)

过时的OnActivityResult(二)

作者: 浪够_ | 来源:发表于2021-03-17 15:04 被阅读0次

    针对上篇《过时的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);
    }
    

    相关文章

      网友评论

          本文标题:过时的OnActivityResult(二)

          本文链接:https://www.haomeiwen.com/subject/owcecltx.html