onActivityResult → ActivityResult API
老写法(Java)
java
// 启动
Intent intent = new Intent(this, SelectActivity.class);
startActivityForResult(intent, REQUEST_CODE_SELECT);
// 回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_SELECT && resultCode == RESULT_OK && data != null) {
String result = data.getStringExtra("selected");
updateUI(result);
}
}
问题在哪里
requestCode 是 int 常量,多个页面间容易重复导致逻辑混淆。onActivityResult 里 if-else 链随着页面增多越来越长。如果调用方在 Fragment 里,还要处理 result 先传到宿主 Activity 再分发的额外逻辑。
新写法(ActivityResult API)
kotlin
// 定义契约
private val selectLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val selected = result.data?.getStringExtra("selected")
updateUI(selected)
}
}
// 启动 --- 不需要 requestCode
selectLauncher.launch(Intent(this, SelectActivity::class.java))
Fragment 间回传结果:
kotlin
// FragmentA
setFragmentResultListener("selectKey") { _, bundle ->
val selected = bundle.getString("selected")
updateUI(selected)
}
// FragmentB
setFragmentResult("selectKey", Bundle().apply {
putString("selected", "结果")
})
parentFragmentManager.popBackStack()
一句话注意
registerForActivityResult 必须在 onCreate 或之前的生命周期中注册(即 Fragment 的 onCreate 或 Activity 的 onCreate),不能在 onResume 或按钮点击后再注册,否则会抛异常。
Fragment 间的 setFragmentResultListener 和 setFragmentResult 只需要同一个 requestKey 匹配,不需要任何 requestCode,代码比旧的 onActivityResult 干净太多。
Java Android 老项目迁移系列,持续更新中。