如何用ActivityResultRegistry处理其他类启动的Intent返回结果?
我有一个不可修改的静态方法launchIntent(),用来启动Intent,方法定义如下:
public static void launchIntent() { ... }
想知道在调用该方法的Fragment类里,用ActivityResultRegistry处理Intent返回结果的最新方案是什么?
背景:之前用请求码配合onActivityResult处理结果,但这个方法已经废弃了,想换成ActivityResultRegistry实现。当前的旧代码是这样的:
public class SomeClass extends Fragment { public void onSomeEvent() { AnotherClass.launchIntent(); } @Override public void onActivityResult(int request, int result, Intent i){ if (request == Constants.LaunchIntentCode){ // 处理AnotherClass.launchIntent()返回的结果 } } }
我试过下面的写法,但因为launchIntent()是无返回值的void方法,不符合API契约,代码无效:
final ActivityResultLauncher intentResultLauncher = registerForActivityResult( SomeClass.launchIntent(), result -> { ... }); intentResultLauncher.launch()
解决方案
核心思路是:既然改不了launchIntent()的实现,我们可以自定义一个ActivityResultContract,把原静态方法里启动Intent的逻辑封装进去,适配ActivityResultAPI的要求,然后用ActivityResultLauncher来启动Intent,替代原静态方法的调用。
步骤1:自定义ActivityResultContract
这个契约要实现ActivityResultContract<Void, ActivityResult<Intent>>,前者表示启动时不需要额外参数,后者表示返回结果包含状态码和Intent。在createIntent方法里复制原launchIntent()中创建Intent的逻辑:
public class LaunchIntentContract extends ActivityResultContract<Void, ActivityResult<Intent>> { @NonNull @Override public Intent createIntent(@NonNull Context context, Void input) { // 这里完全复制原launchIntent()内部创建Intent的逻辑 // 比如原方法里是 new Intent(context, TargetActivity.class),就照搬过来 return new Intent(context, TargetActivity.class); } @Override public ActivityResult<Intent> parseResult(int resultCode, @Nullable Intent intent) { // 把状态码和Intent打包成ActivityResult返回 return new ActivityResult<>(resultCode, intent); } }
步骤2:在Fragment中注册并使用ActivityResultLauncher
在Fragment的onCreate方法里注册Launcher,替换原来的onActivityResult逻辑,然后用Launcher的launch()方法替代原静态方法的调用:
public class SomeClass extends Fragment { private ActivityResultLauncher<Void> intentResultLauncher; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 注册Launcher,处理返回结果 intentResultLauncher = registerForActivityResult( new LaunchIntentContract(), result -> { int resultCode = result.getResultCode(); Intent data = result.getData(); // 原来的请求码判断可以去掉,直接根据结果码和数据处理 if (resultCode == Activity.RESULT_OK && data != null) { // 这里写处理结果的逻辑 } } ); } public void onSomeEvent() { // 用Launcher启动Intent,替代原AnotherClass.launchIntent()调用 intentResultLauncher.launch(null); } }
特殊情况处理
如果原launchIntent()内部的Intent创建逻辑无法直接复制(比如用到了私有参数或方法),尽量不要用反射去硬解,优先找其他方式复用Intent创建逻辑;如果实在必须调用原静态方法,那只能通过自定义Fragment/Activity拦截startActivityForResult调用,但这种方式复杂度高,不推荐。
内容的提问来源于stack exchange,提问作者Dash

