Android registerForActivityResult接口启动activity时报错

registerForActivityResult的用法

Intent intent = new Intent();
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
    @Override
    public void onActivityResult(ActivityResult result) {
        
    }
}).launch(intent);

报错内容

registerLifecycleOwners must call register before they are STARTED.

这句报错的意思时,

生命周期所有者必须在开始之前调用

​​​但如果我们要在onPause或者onStop或者onDestroy中启动下一个activity该怎么办?

解决方案

在onStart或者onCreate中先创建

private ActivityResultLauncher<Intent> activityResultLauncher;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
        if (Settings.canDrawOverlays(BabyProMainActivity.this)) {
            sendBroadcast();
        }
    });
}

然后在需要启动activity的位置添加

Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
activityResultLauncher.launch(intent);

这样运行就完成了在本页面生命周期结束的位置开启新的activity。

原因分析(跟踪源码)

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

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

@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.");
    }
    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);
            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<I, ?> getContract() {
            return contract;
        }
    };
}

在源码中发现了抛异常的位置

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

意思是,注册的必须要在start或者其之前完成。

这也是为何解决方案中ActivityResultLauncher<Intent> activityResultLauncher放在onStart或者onCreate中完成的原因。

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
registerForActivityResult是一个在Android中用于启动Activity并获取返回结果的函数。它是在源码废弃了startActivityForResult方法后的推荐替代方案。通过registerForActivityResult函数,我们可以注册一个ActivityResultLauncher,它可以处理Activity启动和返回结果。这个函数需要两个参数,一个是ActivityResultContract用于定义输入和输出类型,另一个是ActivityResultCallback用于处理返回结果。通过创建ActivityResultContract的实现类,我们可以定义启动页面所需的Intent对象,并在createIntent方法中传入需要传递的参数。同,我们还可以在parseResult方法中解析页面回传的数据,相当于之前的onActivityResult方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [registerForActivityResult 用法详解及适配 Android 10、11](https://blog.csdn.net/java_android_man/article/details/120809631)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Android使用registerForActivityResult动态申请权限](https://blog.csdn.net/weixin_50285953/article/details/120122234)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Android 带回调的启动Activity 推荐使用registerForActivityResult](https://blog.csdn.net/Ikulm/article/details/119798336)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会写代码的猴子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值