首页 > 其他分享 >Android深入学习之ComponentActivity.registerForActivityResult()方法

Android深入学习之ComponentActivity.registerForActivityResult()方法

时间:2023-11-23 20:14:00浏览次数:47  
标签:NonNull registerForActivityResult ComponentActivity contract ActivityResultLaunc

ComponentActivity.startActivityForResult()和ComponentActivity.onActivityResult()已经废弃,如下图所示,取而代之的是统一它俩的ActivityResultLauncher。

  

ActivityResultLauncher对象可以通过ComponentActivity.registerForActivityResult()方法获取。该方法有两个重载。

public final @NonNull ActivityResultLauncher<I> <I, O> registerForActivityResult(
    @NonNull ActivityResultContract<I, O> contract,
    @NonNull ActivityResultCallback<O> callback
)

public final @NonNull ActivityResultLauncher<I> <I, O> registerForActivityResult(
    @NonNull ActivityResultContract<I, O> contract,
    @NonNull ActivityResultRegistry registry,
    @NonNull ActivityResultCallback<O> callback
)

第一个registerForActivityResult()方法的源代码如下:

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

它拿着mActivityResultRegistry对象去调用了第二个registerForActivityResult()方法。第二个registerForActivityResult()方法的源代码如下:

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

mActivityResultRegistry是ComponentActivity中定义并初始化的一个ActivityResultRegistry类型变量。

ActivityResultRegistry是个抽象类,其中定义的抽象方法是

@MainThread
public abstract void <I, O> onLaunch(
    int requestCode,
    @NonNull ActivityResultContract<I, O> contract,
    I input,
    @Nullable ActivityOptionsCompat options
)

此外还有两个被final修饰的register()方法

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

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

上方registerForActivityResult()方法就是调用了第二个register()方法,源代码如下:

@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.");
        }

        registerKey(key);
        LifecycleContainer lifecycleContainer = mKeyToLifecycleContainers.get(key);
        if (lifecycleContainer == null) {
            lifecycleContainer = new LifecycleContainer(lifecycle);
        }
        LifecycleEventObserver observer = new LifecycleEventObserver() {
            @Override
            @SuppressWarnings("deprecation")
            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) {
                Integer innerCode = mKeyToRc.get(key);
                if (innerCode == null) {
                    throw new IllegalStateException("Attempting to launch an unregistered "
                            + "ActivityResultLauncher with contract " + contract + " and input "
                            + input + ". You must ensure the ActivityResultLauncher is registered "
                            + "before calling launch().");
                }
                mLaunchedKeys.add(key);
                try {
                    onLaunch(innerCode, contract, input, options);
                } catch (Exception e) {
                    mLaunchedKeys.remove(key);
                    throw e;
                }
            }

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

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

其中,下方代码就说明了官方文档的那句

registerForActivityResult() must be called unconditionally, as part of initialization path, typically as a field initializer of an Activity or Fragment.

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.");
        }

即,registerForActivityResult()需要在Activity的状态是STARTED之前被调用。也就是,在定义ActivityResultLauncher变量时,或者在构造函数里,或者在onCreate()/onStart()方法里。

标签:NonNull,registerForActivityResult,ComponentActivity,contract,ActivityResultLaunc
From: https://www.cnblogs.com/larissa-0464/p/17381330.html

相关文章

  • Android 混淆打包后gson报错Missing type parameter
    原文:Android混淆打包后gson报错Missingtypeparameter-Stars-One的杂货小窝记录一个简单的bug在代码中使用了gson将json转为list:valjson=""valplanList=gson.fromJson<List<PrayerPlan>>(json,object:TypeToken<List<PrayerPlan>>(){}.type)然后线上的时候......
  • 【Android 逆向】frida 检测绕过
    参考地址:1.aaa.apk安装到手机,是一个叫玩吧的应用./hooker......23248浏览器com.browser2345_oem32541玩吧com.wodi.who......
  • 【Android R】manualTests#com.android.cts.verifier.security.FingerprintBoundKeysT
    异常日志:11-1219:24:47.64953875387DAndroidRuntime:ShuttingdownVM11-1219:24:47.67153875387EAndroidRuntime:FATALEXCEPTION:main11-1219:24:47.67153875387EAndroidRuntime:Process:com.android.cts.verifier,PID:538711-1219:24:47.6715387......
  • 使用 Android Studio 开发一款弹钢琴app
    A.项目描述本项目主要实现了【钢琴键盘的模拟】、【弹奏引导】以及【乐曲库】等功能。钢琴键盘模拟:提供全尺寸键盘,并且根据用户的喜好来调整键盘的颜色样式。弹奏引导:用户可以根据键盘上的提示符号......
  • android.content.res.Resources$NotFoundException: String resource ID #0x1
    在Android开发中如果出现android.content.res.Resources$NotFoundException:StringresourceID#0x1这样的错误,你想也不用想,一定是Textview控件显示数据出了问题:mTextview.setText(这里的传入的数据一定写成int类型了)。我们需要做的是eg:mTextview.setText(1+""),也就是参数转......
  • android studio 添加按钮事件实现加一操作
    androidstudio添加按钮事件实现加一操作要在AndroidStudio中为按钮添加一个加一(+1)的操作,你可按照下列步骤实现:通过在XML布局中添加按钮,导入一个Button组件: XML复制代码<Buttonandroid:id="@+id/add_button"android:layout_width="wrap_content"andro......
  • 深入Android多线程编程与性能优化
    引言在上一篇的入门篇中,我们对Android线程的基础概念和多线程编程模型有了初步了解。本篇将深入探讨多线程编程技术和性能优化策略,以提升应用的效率和响应性。高级多线程编程技术使用线程池管理线程线程池是一组预先创建的线程,用于执行任务。通过使用线程池,可以避免不断创建和销毁......
  • Android 的PAI 简介
    PAI简介在Google的Android操作系统中,PAI(PreinstalledAppsInfrastructure)预安装程序基础设施是指在设备出厂时预先安装在系统中的一组应用程序。这些应用程序通常是由设备制造商或运营商选择的,并且它们在设备启动时就已经存在,用户可以在使用设备时直接访问这些应用。预安装介绍......
  • 作为一个Android初级开发工程师,该如何进阶?
    前言现今Android行业初级人才已逐渐饱和化,但中高级人才却依旧很稀缺,身边HR朋友经常遇到的情况是:100份简历里只有2、3个比较合适的候选人,大部分的人都是不合格的!有97%的Android技术人都会面临这些困境(或许也是你的困惑):缺乏技术广度和深度:如果你长期在小型软件公司或外包工......
  • 弹钢琴 app,Android 开发实战
    A.项目描述本项目主要实现了【钢琴键盘的模拟】、【弹奏引导】以及【乐曲库】等功能。钢琴键盘模拟:提供全尺寸键盘,并且根据用户的喜好来调整键盘的颜色样式。弹奏引导:用户可以根据键盘上的提示符号......