You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RegisterForActivityResult API:启动Activity遇配置变更无法返回结果

解决Activity配置变更后无法返回结果的问题

问题场景

现有Activity A与Activity B的实现逻辑:

  • Activity A 通过 registerForActivityResult 启动Activity B,并接收其返回的Intent数据
  • Activity B 的RecyclerView列表项点击时,设置返回结果并关闭自身
  • 应用已锁定竖屏避免旋转配置变更,但需适配字体/显示大小调整引发的UI重绘配置变更
  • 当Activity B因配置变更销毁重建后,点击列表项无法将结果返回给Activity A,且A、B的ViewModel无关联

解决方案

方案一:避免Activity B因配置变更销毁重建

在AndroidManifest.xml中为Activity B添加configChanges属性,指定需要手动处理的配置项,让系统在这些配置变更时不销毁重建Activity,而是调用onConfigurationChanged方法:

<activity
    android:name=".ActivityB"
    android:configChanges="fontScale|screenSize|smallestScreenSize|layoutDirection"
    <!-- 其他原有属性 -->
    />

之后在Activity B中重写onConfigurationChanged方法,处理UI适配逻辑:

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    // 根据新配置更新UI,比如刷新RecyclerView内容
    recyclerView.adapter?.notifyDataSetChanged()
}

优点:直接规避配置变更导致的Activity销毁重建问题;缺点:需要手动处理所有指定配置项的UI适配逻辑。


方案二:用ViewModel保存待返回结果状态

利用ViewModel的生命周期独立性(不受Activity配置变更影响),保存待返回的结果,确保Activity B重建后能继续返回结果:

  1. 为Activity B创建ViewModel:
class ActivityBViewModel : ViewModel() {
    // 保存待返回的结果码和Intent
    var pendingResult: Pair<Int, Intent>? = null
}
  1. 在Activity B中获取ViewModel:
private val viewModel by viewModels<ActivityBViewModel>()
  1. 列表项点击时,将结果存入ViewModel并关闭:
// RecyclerView列表项点击事件处理
holder.itemView.setOnClickListener {
    val targetData = // 获取当前列表项的数据
    val resultIntent = Intent().apply {
        putExtra("key", targetData)
    }
    // 将结果存入ViewModel
    viewModel.pendingResult = Pair(Activity.RESULT_OK, resultIntent)
    finish()
}
  1. 在Activity B的onCreate中检查待返回结果,若存在则立即返回:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 初始化视图逻辑...
    
    // 检查是否有待返回的结果,若有则立即返回给Activity A
    viewModel.pendingResult?.let { (code, intent) ->
        setResult(code, intent)
        finish()
    }
}

优点:ViewModel自动处理状态保留,无需手动序列化数据;缺点:仅适用于Activity未被系统回收的场景。


方案三:用SavedInstanceState持久化结果状态

如果需要应对进程被杀的极端情况,可结合SavedInstanceState持久化待返回结果:

  1. 在Activity B中定义常量和成员变量:
companion object {
    private const val KEY_RESULT_CODE = "result_code"
    private const val KEY_RESULT_INTENT = "result_intent"
}

private var pendingResultCode = Activity.RESULT_CANCELED
private var pendingResultIntent: Intent? = null
  1. 重写onSaveInstanceState保存结果状态:
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    // 仅当存在待返回结果时才保存
    if (pendingResultCode != Activity.RESULT_CANCELED && pendingResultIntent != null) {
        outState.putInt(KEY_RESULT_CODE, pendingResultCode)
        outState.putParcelable(KEY_RESULT_INTENT, pendingResultIntent)
    }
}
  1. 在onCreate中恢复状态并返回结果:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 初始化视图逻辑...
    
    savedInstanceState?.let {
        pendingResultCode = it.getInt(KEY_RESULT_CODE, Activity.RESULT_CANCELED)
        pendingResultIntent = it.getParcelable(KEY_RESULT_INTENT)
        
        // 若恢复到待返回结果,立即返回给Activity A
        if (pendingResultCode != Activity.RESULT_CANCELED && pendingResultIntent != null) {
            setResult(pendingResultCode, pendingResultIntent)
            finish()
        }
    }
}
  1. 列表项点击时设置待返回状态:
holder.itemView.setOnClickListener {
    val targetData = // 获取当前列表项的数据
    pendingResultIntent = Intent().apply {
        putExtra("key", targetData)
    }
    pendingResultCode = Activity.RESULT_OK
    finish()
}

优点:即使进程被杀也能恢复状态;缺点:需要手动处理数据的序列化/反序列化,仅支持Parcelable类型的数据。


内容的提问来源于stack exchange,提问作者MajinKenn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:09:51