registerForActivityResult(上)

registerForActivityResult(下)
相关库

~~startActivityForResult~~被标注弃用,推荐使用registerForActivityResult,查看源码发现其实就是对startActivityForResultonActivityResult的封装。

整体代码比较简单,关注几个关键方法即可。

ActivityResultRegistry#register

调用registerForActivityResult方法时,会生成一个key值并调用ActivityResultRegistryregister。在register方法中会将key值缓存起来,并生成一个requestCode,这个code就是startActivityForResult所用需要用到的。

    private int registerKey(String key) {
      
        Integer existing = mKeyToRc.get(key);
        if (existing != null) {
            return existing;
        }
        //生成requestCode
        int rc = generateRandomNumber();
        //将requestCode和key值绑定,并缓存起来
        bindRcKey(rc, key);
        return rc;
    }

在经过一些生命周期判断,异常判断,最后返回一个ActivityResultLauncher对象,这个对象就是调用registerForActivityResult的返回值

        return new ActivityResultLauncher() {
            @Override
            public void launch(I input, @Nullable ActivityOptionsCompat options) {
                //缓存key,获取code
                mLaunchedKeys.add(key);
                Integer innerCode = mKeyToRc.get(key);
                onLaunch((innerCode != null) ? innerCode : requestCode, contract, input, options);
            }

            @Override
            public void unregister() {
                ActivityResultRegistry.this.unregister(key);
            }

            @NonNull
            @Override
            public ActivityResultContract getContract() {
                return contract;
            }
        };

可以看到当我们调用launch方法时,实际上拿到requestcode,传递给onLaunch回调方法,这个方法其实启动activity的实现,

ActivityResultRegistry#onLaunch

ComponentActivity中实现了ActivityResultRegistry的onLaunch方法,该方法最终调用了(权限请求时,调用的是ActivityCompat.requestPermissions)

ActivityCompat.startActivityForResult(activity, intent, requestCode, optionsBundle);

所以launch,最终调用的是startActivityForResult

ActivityResultCallback

前面梳理了activity的启动过程,接下来看看activity的数据回传结果是如果实现的吧。

前面知道内部仍然调用startActivityForResult,所以回调我们直接查看onActivityResult

    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    public final boolean dispatchResult(int requestCode, int resultCode, @Nullable Intent data) {
       //通过code反找key
        String key = mRcToKey.get(requestCode);
        if (key == null) {
            return false;
        }
        mLaunchedKeys.remove(key);
        //通过key找到缓存的ActivityResultCallback,ActivityResultContract
        doDispatch(key, resultCode, data, mKeyToCallback.get(key));
        return true;
    }

     private  void doDispatch(String key, int resultCode, @Nullable Intent data,
            @Nullable CallbackAndContract callbackAndContract) {
        if (callbackAndContract != null && callbackAndContract.mCallback != null) {
            ActivityResultCallback callback = callbackAndContract.mCallback;
            ActivityResultContract contract = callbackAndContract.mContract;
            //封装返回的数据,并调用callback,完成回调
            callback.onActivityResult(contract.parseResult(resultCode, data));
        } else {
            // Remove any parsed pending result
            mParsedPendingResults.remove(key);
            // And add these pending results in their place
            mPendingResults.putParcelable(key, new ActivityResult(resultCode, data));
        }
    }

其中ActivityResultContract功能很简单,就是对我们传入intent,和返回的intent进行处理封装的。

使用上的不便

功能实现上是ok,但是使用时有一个不方便的地方就是registerForActivityResult对调用时所在的生命周期有要求。

if (lifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
            throw new IllegalStateException("LifecycleOwner " + lifecycleOwner + " is "
                    + "attempting to register while current state is "
                    + lifecycle.getCurrentState() + ". LifecycleOwners must call register before "
                    + "they are STARTED.");
        }

上面的异常就限制了我必须在started状态之前就提前定义并调用registerForActivityResult方法,等到需要启动时在调用launch方法,并不能随用随调。
可以通过二次封装的形式达到随意调用。

你可能感兴趣的:(registerForActivityResult(上))