【Android】页面返回结果异常:resultCode == 0 的问题

问题

在 Android 开发中,我们经常需要在页面之间传递数据。最近在做一个页面跳转并返回结果的功能时,遇到了一个棘手的问题:从 B 页面返回 A 页面时,A 页面始终收到 resultCode = 0(即 RESULT_CANCELED),明明在 B 页面已经设置了 setResult(RESULT_OK, intent)。

问题场景还原

先简单描述一下我的需求:

A 页面(管理页)通过按钮跳转到 B 页面(创建页)

在 B 页面操作完成后,点击返回键回到 A 页面,并携带返回数据

A 页面接收数据并提示用户

关键代码片段、
A 页面(接收结果):
// 注册返回结果监听器
private val intentActivityCreateResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    // 这里始终收到 resultCode = 0
    if (result.resultCode == RESULT_OK) {
        Log.e("Vehicle", "返回管理页面")
        result.data?.let { data ->
            val resultStr = data.getStringExtra("result")
            ToastUtil.showMessageBottom(this, "从创建页面返回:$resultStr")
        }
    } else {
        Log.e("Vehicle", "resultCode 异常:${result.resultCode}") // 总是打印 0
    }
}

// 跳转按钮点击事件
binding?.btnCreateVehicle?.setOnClickListener {
    val intent = Intent(this, ParamVehicleCreateActivity::class.java)
    intentActivityCreateResult.launch(intent) // 跳转到 B 页面
}
B 页面(返回数据):
// 监听返回键
override fun onBackPressed() {
    super.onBackPressed() // 先调用父类方法
    // 后设置返回结果
    val intent = Intent()
    intent.putExtra("result", "修改完成")
    setResult(RESULT_OK, intent)
    finish()
}

运行后发现,A 页面的 resultCode 始终是 0,完全不符合预期。

问题根源:super.onBackPressed() 的执行顺序

排查发现,问题出在 B 页面的 onBackPressed() 方法执行顺序 上。

super.onBackPressed() 是父类 Activity 的方法,它的默认实现是 直接关闭当前页面(相当于调用 finish()),并且会自动设置 resultCode = RESULT_CANCELED(值为 0)。

在我最初的代码里:

先调用 super.onBackPressed() → 页面开始关闭,resultCode 被设为 0
再调用 setResult(RESULT_OK, intent) → 此时页面已经在关闭流程中,这个设置根本不会生效

简单说就是:页面都要关了,再设置返回结果已经来不及了。

解决方案:调整代码执行顺序

既然知道了问题原因,解决方法就很简单了:先设置返回结果,再执行页面关闭逻辑。

修改 B 页面的 onBackPressed() 方法:

override fun onBackPressed() {
    // 第一步:先设置返回结果(必须在页面关闭前执行)
    val intent = Intent()
    intent.putExtra("result", "修改完成")
    setResult(RESULT_OK, intent) // 关键:先设置结果
    
    // 第二步:再执行关闭逻辑
    super.onBackPressed() // 父类方法内部会调用 finish()
    // 也可以直接用 finish() 替代,效果相同
    // finish()
}

修改后重新运行,A 页面终于能收到 resultCode = -1(即 RESULT_OK),数据也能正常传递了!

扩展:其他返回场景的处理

除了物理返回键,用户还可能通过其他方式返回(比如顶部导航栏的返回按钮、手势返回),为了确保所有场景都能正确返回结果,我们需要额外处理这些情况。

1. 顶部导航栏返回按钮

如果页面使用了 ActionBar 或 Toolbar 的返回按钮,需要在 onOptionsItemSelected 中处理:

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        android.R.id.home -> { // 顶部导航栏返回按钮
            // 同样先设置返回结果
            val intent = Intent()
            intent.putExtra("result", "修改完成")
            setResult(RESULT_OK, intent)
            finish() // 关闭页面
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}
2. 手势返回(全面屏手机)

如果应用支持手势返回(从屏幕左侧 / 右侧滑动返回),需要重写 onBackPressedDispatcher 的回调:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 处理手势返回
    onBackPressedDispatcher.addCallback(this) {
        val intent = Intent()
        intent.putExtra("result", "修改完成")
        setResult(RESULT_OK, intent)
        finish()
    }
}
总结

页面返回结果时,resultCode 总是 0 的问题,本质是 setResult() 与页面关闭逻辑的执行顺序 导致的。记住一个原则:

先调用 setResult() 设置返回结果,再执行页面关闭操作(super.onBackPressed() 或 finish())

正确的代码模板(B 页面):
// 物理返回键处理
override fun onBackPressed() {
    // 1. 先设置返回结果
    val intent = Intent()
    intent.putExtra("key", "需要返回的数据")
    setResult(RESULT_OK, intent)
    
    // 2. 再关闭页面
    super.onBackPressed() // 或直接 finish()
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值