源码分析之 registerForActivityResult

472 阅读2分钟
activityResultLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        //这里相当于以前的onActivityResult
        Log.d(TAG,
            "there is receiver data: ${it.data}");
    }
    
    
val intent = Intent(requireActivity(), SimpleSecondActivity::class.java)
    .putExtra("page", PageContainer.task)
    activityResultLauncher.launch()
    
    //activityResultLauncher利用这个来startActivity
    
ActivityResultRegistry 主要任务是register和分发返回结果dispatchResult

ActivityResultContract 在register入参需要传递,指定你和下个界面入参和出参的数据。是个包装的数据bean

我们首先从fragment打开一个界面入手调用registerForActivityResult

1.1 [->fragment.java]

public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
        @NonNull final ActivityResultContract<I, O> contract,//系统有默认实现,也可以构造自己的contract
        @NonNull final ActivityResultCallback<O> callback) { //回调activityResult的callback
    return prepareCallInternal(contract, new Function<Void, ActivityResultRegistry>() {
        @Override
        public ActivityResultRegistry apply(Void input) {
            if (mHost instanceof ActivityResultRegistryOwner) {
                return ((ActivityResultRegistryOwner) mHost).getActivityResultRegistry();
            }
            return requireActivity().getActivityResultRegistry();//ActivityResultRegistry 默认activity有一个成员变量实现
        }
    }, callback);
}

1.2 [->fragment.java]

@NonNull
private <I, O> ActivityResultLauncher<I> prepareCallInternal(
        @NonNull final ActivityResultContract<I, O> contract,
        @NonNull final Function<Void, ActivityResultRegistry> registryProvider,
        @NonNull final ActivityResultCallback<O> callback) {
     //这里有状态校验,说明只能在onCreate和onAttach里才能register调用
    // Throw if attempting to register after the Fragment is CREATED.
    if (mState > CREATED) { 
        throw new IllegalStateException("Fragment " + this + " is attempting to "
                + "registerForActivityResult after being created. Fragments must call "
                + "registerForActivityResult() before they are created (i.e. initialization, "
                + "onAttach(), or onCreate()).");
    }
    final AtomicReference<ActivityResultLauncher<I>> ref = new AtomicReference<>();
    // We can't call generateActivityResultKey during initialization of the Fragment
    // since we need to wait for the mWho to be restored from saved instance state
    // so we'll wait until we have all the information needed to register  to actually
    // generate the key and register.

    registerOnPreAttachListener(new OnPreAttachedListener() {
        @Override
        void onPreAttached() {
            final String key = generateActivityResultKey();
            ActivityResultRegistry registry = registryProvider.apply(null);
            ref.set(registry.register(key, Fragment.this, contract, callback));【见小节2.1】
        }
    });

    return new ActivityResultLauncher<I>() {
        @Override
        public void launch(I input, @Nullable ActivityOptionsCompat options) {
            取出在onPreAttached注册的ActivityResultRegistry进行调用
            ActivityResultLauncher<I> delegate = ref.get();
            if (delegate == null) {
                throw new IllegalStateException("Operation cannot be started before fragment "
                        + "is in created state");
            }
            当你启动activity时会调用这个方法
            delegate.launch(input, options);
        }

        @Override
        public void unregister() {
            ActivityResultLauncher<I> delegate = ref.getAndSet(null);
            if (delegate != null) {
                delegate.unregister();
            }
        }

        @NonNull
        @Override
        public ActivityResultContract<I, ?> getContract() {
            return contract;
        }
    };
}
利用atomicInteger 每次++,这样你注册多次生成的key也是唯一的
private final AtomicInteger mNextLocalRequestCode = new AtomicInteger();

2.1 [->ActivityResultRegistry.java]

@NonNull
public final <I, O> ActivityResultLauncher<I> register(
        @NonNull final String key,
        @NonNull final LifecycleOwner lifecycleOwner,
        @NonNull final ActivityResultContract<I, O> contract,
        @NonNull final ActivityResultCallback<O> callback) {

    Lifecycle lifecycle = lifecycleOwner.getLifecycle();

    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.");
    }
    利用random生成requestCode
    final int requestCode = registerKey(key);
    
    LifecycleContainer lifecycleContainer = mKeyToLifecycleContainers.get(key);
    if (lifecycleContainer == null) {
        lifecycleContainer = new LifecycleContainer(lifecycle);
    }
    LifecycleEventObserver observer = new LifecycleEventObserver() {
        @Override
        public void onStateChanged(
                @NonNull LifecycleOwner lifecycleOwner,
                @NonNull Lifecycle.Event event) {
            if (Lifecycle.Event.ON_START.equals(event)) {
                mKeyToCallback.put(key, new CallbackAndContract<>(callback, contract));
                if (mParsedPendingResults.containsKey(key)) {
                    @SuppressWarnings("unchecked")
                    final O parsedPendingResult = (O) mParsedPendingResults.get(key);
                    mParsedPendingResults.remove(key);
                    callback.onActivityResult(parsedPendingResult);
                }
                final ActivityResult pendingResult = mPendingResults.getParcelable(key);
                if (pendingResult != null) {
                    mPendingResults.remove(key);
                    callback.onActivityResult(contract.parseResult(
                            pendingResult.getResultCode(),
                            pendingResult.getData()));
                }
            } else if (Lifecycle.Event.ON_STOP.equals(event)) {
                mKeyToCallback.remove(key);
            } else if (Lifecycle.Event.ON_DESTROY.equals(event)) {
                unregister(key);
            }
        }
    };
    lifecycleContainer.addObserver(observer);
    mKeyToLifecycleContainers.put(key, lifecycleContainer);

    return new ActivityResultLauncher<I>() {
        @Override
        public void launch(I input, @Nullable ActivityOptionsCompat options) {
            mLaunchedKeys.add(key);
            回调实现类的onLaunch一般是在ComponentActivity里【见小节2.2onLaunch(requestCode, contract, input, options); 
        }

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

        @NonNull
        @Override
        public ActivityResultContract<I, ?> getContract() {
            return contract;
        }
    };
}

利用一个对象里的容器来封装lifecycle,方便统一销毁lifecycle实例

private static class LifecycleContainer {
    final Lifecycle mLifecycle;
    private final ArrayList<LifecycleEventObserver> mObservers;

    LifecycleContainer(@NonNull Lifecycle lifecycle) {
        mLifecycle = lifecycle;
        mObservers = new ArrayList<>();
    }

    void addObserver(@NonNull LifecycleEventObserver observer) {
        mLifecycle.addObserver(observer);
        mObservers.add(observer);
    }

    void clearObservers() {
        for (LifecycleEventObserver observer: mObservers) {
            mLifecycle.removeObserver(observer);
        }
        mObservers.clear();
    }
}

2.2 [->ComponentActivity.java]

@Override
public <I, O> void onLaunch(
        final int requestCode,
        @NonNull ActivityResultContract<I, O> contract,
        I input,
        @Nullable ActivityOptionsCompat options) {
    ComponentActivity activity = ComponentActivity.this;
        从contract里取出intentstartActivity
        Intent intent = contract.createIntent(activity, input);
        // startActivityForResult path
        ActivityCompat.startActivityForResult(activity, intent, requestCode, optionsBundle);

}

2.3 [->ComponentActivity.java]

//当第二个界面setResult finish 后收到数据转发给ActivityResultRegistry去处理
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) {
        super.onActivityResult(requestCode, resultCode, data);
    }
}

2.4 [->ActivityResultRegistry.java]

@MainThread
public final boolean dispatchResult(int requestCode, int resultCode, @Nullable Intent data) {
    通过requestCode来取出保存的key
    String key = mRcToKey.get(requestCode);
    if (key == null) {
        return false;
    }
    移除启动的记录
    mLaunchedKeys.remove(key);
    分发事件
    doDispatch(key, resultCode, data, mKeyToCallback.get(key));
    return true;
}

2.5 [->ActivityResultRegistry.java]

private <O> void doDispatch(String key, int resultCode, @Nullable Intent data,
        @Nullable CallbackAndContract<O> callbackAndContract) {
        从contract里取出callback引用,回调给上层
    if (callbackAndContract != null && callbackAndContract.mCallback != null) {
        ActivityResultCallback<O> callback = callbackAndContract.mCallback;
        ActivityResultContract<?, O> contract = callbackAndContract.mContract;
        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));
    }
}