- 针对老版本没有正确回调onActivityResult问题?
- 使用 ActivityResultContracts(适用于新 API)
- 完整的Android示例
- 总结
当我们用startActivityForResult调用Android系统页面时,会发现未等用户操作完成后直接回调了onActivityResult方法。这种现象在实际应用中肯定不是我们想看到的,最终结果是希望用户操作完后,可以有效的接收到相应的数据。今天我们就来讲一下,如何从不同的角度来解决这个问题?(先来看一张流程图如何解决)
针对老版本没有正确回调onActivityResult问题?
在 Android 中,当你通过 startActivityForResult() 启动另一个 Activity 并返回时,onActivityResult() 会在原 Activity 的 onResume() 之前被调用。这是 Android 系统设计的机制,目的是在 Activity 恢复可见状态前 处理返回的数据。
原理分析,生命周期与数据传递时序
- 设计逻辑:onActivityResult() 的目的是在目标 Activity 关闭后,立即处理返回的数据,以便在 Activity 重新进入前台(onResume())时,界面能基于最新的数据更新。
- 系统流程(当从目标 Activity 返回时,系统会按以下顺序执行):
- 关闭目标 Activity(触发其 onDestroy())。
- 恢复原 Activity 的 onActivityResult()(传递数据)。
- 触发原 Activity 的 onResume()(界面可见)。
- 根据 Android 开发者文档:onActivityResult() is called before onResume() when an activity exits.
因此这种情况我们就需要通过onResume回调来处理和再次校验你的业务逻辑,下面输出onResume回调过程的处理方案:
-
步骤1:直接处理(需要结合后续步骤兼容)
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {//这里处理业务逻辑} }
-
步骤2:在 onActivityResult() 中更新标志位,通过变量标记数据是否已处理,在 onResume() 中检查该标志(因为这种情况onActivityResult 优先调用于onResume)
private boolean mIsResultHandled = false;@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {String result = data.getStringExtra("data");// 处理数据mIsResultHandled = true;} }@Override protected void onResume() {super.onResume();if (!mIsResultHandled) {// 处理未返回数据的场景} }
-
步骤3:如果从 Fragment 中调用 startActivityForResult(),因为Fragment 的 onActivityResult() 优先于所属 Activity 的 onActivityResult() 被调用。若 Activity 未重写 onActivityResult(),或未调用 super.onActivityResult(),Fragment 可能导致无法收到回调。所以这种情况一般都会将相关逻辑通过eventBus发送到主Activity来处理。