startActivityForResult的替代方法:registerForActivityResult

Quibbler 2023-7-28 895

startActivityForResult的替代方法:registerForActivityResult


        在startActivityForResult的用法一文的最后提到startActivityForResult方法已经废弃,推荐使用AndroidX中的registerForActivityResult方法。

    @NonNull
    @Override
    public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
            @NonNull ActivityResultContract<I, O> contract,
            @NonNull ActivityResultCallback<O> callback) {
        return registerForActivityResult(contract, mActivityResultRegistry, callback);
    }

        将ActivityResultCallback注册到ActivityResultRegistry中:

    @NonNull
    @Override
    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);
    }



1、registerForActivityResult

        以注册获取启动Activity返回的结果为例,这里借助ActivityResultContracts,提供了丰富的实现,只需要通过其中的StartActivityForResult()方法即可获取ActivityResultContract<Intent, ActivityResult>

    val register:ActivityResultContract<Intent, ActivityResult> = ActivityResultContracts.StartActivityForResult()

        然后再重写ActivityResultCallback接口:

    val callback = object : ActivityResultCallback<ActivityResult> {
	override fun onActivityResult(result: ActivityResult?) {
		Log.d("TAG", "resultCode:${result?.resultCode}  data:${result?.data}")
	}
    }

        用前面提到的registerForActivityResult()方法将两者注册:

    registerForActivityResult(register, callback)

        会获得返回的ActivityResultLauncher对象:

    val launcher: ActivityResultLauncher<Intent> = registerForActivityResult(register, callback)

        通过该ActivityResultLauncher可以启动我们的Activity

    val intent = Intent()
    //
    
    launcher.launch(intent)

        看到这里它的优势相比也显而易见,将繁杂的注册和结果回调解耦,不用全部集中在Activity的一个onActivityResult()回调方法中。且每种不同的业务启动不同的Activity,都可以有自己独立的launcher和处理回调。



2、各种ActivityResultContract

        Android开发中除了获取启动Activity返回的结果,申请权限的回调。还有非常多的场景,可以通过实现ActivityResultContract<I,O>完成不同场景下的启动:

    abstract class ActivityResultContract<I, O> {
	/**
	 * Create an intent that can be used for [android.app.Activity.startActivityForResult].
	 */
	abstract fun createIntent(context: Context, input: I): Intent
	
	/**
	 * Convert result obtained from [android.app.Activity.onActivityResult] to [O].
	 */
	abstract fun parseResult(resultCode: Int, intent: Intent?): O
	
	/**
	 * An optional method you can implement that can be used to potentially provide a result in
	 * lieu of starting an activity.
	 *
	 * @return the result wrapped in a [SynchronousResult] or `null` if the call
	 * should proceed to start an activity.
	 */
	open fun getSynchronousResult(context: Context, input: I): SynchronousResult<O>? {
		return null
	}
	
	/**
	 * The wrapper for a result provided in [getSynchronousResult]. This allows differentiating
	 * between a null [T] synchronous result and no synchronous result at all.
	 */
	class SynchronousResult<T>(val value: T)
    }

        而且ActivityResultContracts也提供了非常多现成的实现,比如启动文件选择、获取照片选择结果、启动相机拍照获取结果等等。




3、registerForActivityResult原理

        前面了解了startActivityForResult的原理registerForActivityResult其实也一样,它的注册流程如下:

        通过返回的ActivityResultLauncher启动Activity流程:

        接着startActivityForResult的原理一文,我们知道结果回调。这里AndroidX库中的ComponentActivity重写了onActivityResult()回调方法:

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

        通过前面注册的mActivityResultRegistry分发处理这次回调结果,如果没有被处理,还是走原来的处理onActivityResult()回调逻辑。

    @MainThread
    public final boolean dispatchResult(int requestCode, int resultCode, @Nullable Intent data) {
        String key = mRcToKey.get(requestCode);
        if (key == null) {
            return false;
        }
        doDispatch(key, resultCode, data, mKeyToCallback.get(key));
        return true;
    }

        紧接着调用doDispatch()方法处理分发结果:

    private <O> void doDispatch(String key, int resultCode, @Nullable Intent data,
            @Nullable CallbackAndContract<O> callbackAndContract) {
        if (callbackAndContract != null && callbackAndContract.mCallback != null
                && mLaunchedKeys.contains(key)) {
            ActivityResultCallback<O> callback = callbackAndContract.mCallback;
            ActivityResultContract<?, O> contract = callbackAndContract.mContract;
            callback.onActivityResult(contract.parseResult(resultCode, data));
            mLaunchedKeys.remove(key);
        } else {
            // Remove any parsed pending result
            mParsedPendingResults.remove(key);
            // And add these pending results in their place
            mPendingResults.putParcelable(key, new ActivityResult(resultCode, data));
        }
    }

        最终是在我们注册的ActivityResultCallback回调中处理onActivityResult结果:

    /**
	* A type-safe callback to be called when an {@link Activity#onActivityResult activity result}
	* is available.
	*
	* @param <O> result type
    */
    public interface ActivityResultCallback<O> {
	/**
	 * Called when result is available
		*/
	void onActivityResult(@SuppressLint("UnknownNullness") O result);
    }

        上面整体的流程是:


不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com