文章目录
- 为什么旧方案被弃用
- Activity Result API 的核心组成
- 注册 Launcher
- Launcher 到底是什么
- 启动目标 Activity
- 在第二个 Activity 中返回结果
- 回调中的 result 是什么
- resultCode
- data
- 为什么 registerForActivityResult 要放在 onCreate 中
- 数据是如何返回的
- Activity Result API 的完整流程
- 总结
在学习 Android 的 Activity 通信时,最先接触到的通常是
Intent和putExtra()。启动另一个 Activity 很简单,但如果希望打开一个 Activity,等待它处理完成,再把结果返回给当前 Activity,事情就会稍微复杂一些。很多教材仍然使用startActivityForResult()和onActivityResult(),但这套方案已经被官方弃用。现在 Android 推荐使用Activity Result API,它不仅写法更清晰,也更符合 Activity 生命周期的设计。
本文从基础开始,结合完整代码,一步步理解 Activity Result API 的工作方式。
为什么旧方案被弃用
旧版写法大致如下:
startActivityForResult(intent,100);然后在当前 Activity 中重写:
@OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){...}所有返回结果都会集中到这一个方法中,再根据requestCode判断是谁返回的。
当项目变大之后,一个 Activity 可能启动很多不同的页面,onActivityResult()会越来越长,需要不断写if或switch判断,代码可读性和维护性都会变差。
Activity Result API 的思路是:谁发起请求,谁直接注册回调处理结果。
这样结果处理逻辑就和启动逻辑放在一起,不再需要统一集中处理。
Activity Result API 的核心组成
整个 API 只有三个核心部分。
首先是Launcher。Launcher 可以理解成一个“启动器”,专门负责启动某种操作,例如启动另一个 Activity、打开相册、请求权限等。
其次是Contract(ActivityResultContract)。Contract 用来规定:
- 启动时需要传什么参数;
- 返回时会得到什么类型的数据。
最后是回调函数。当目标 Activity 结束后,系统会自动调用回调,把结果交给当前 Activity。
整个流程可以概括为:
注册 Launcher
↓
launch()
↓
启动目标 Activity
↓
目标 Activity 返回结果
↓
自动执行回调
注册 Launcher
先创建一个简单的页面。
MainActivity 中放一个按钮:
publicclassMainActivityextendsAppCompatActivity{privateActivityResultLauncher<Intent>launcher;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);launcher=registerForActivityResult(newActivityResultContracts.StartActivityForResult(),result->{if(result.getResultCode()==RESULT_OK){Intentdata=result.getData();Stringtext=data!=null?data.getStringExtra("result"):null;Toast.makeText(this,text,Toast.LENGTH_SHORT).show();}});findViewById(R.id.btnOpen).setOnClickListener(v->{Intentintent=newIntent(this,SecondActivity.class);launcher.launch(intent);});}}这里最重要的是:
registerForActivityResult(...)这个方法完成了 Launcher 的注册。它需要两个参数:
registerForActivityResult(contract,callback)第一个参数是 Contract。
newActivityResultContracts.StartActivityForResult()表示:启动一个普通 Activity,并等待它返回结果。
第二个参数是回调函数。当 SecondActivity 结束时,这里的代码会自动执行。
Launcher 到底是什么
很多初学者看到:
privateActivityResultLauncher<Intent>launcher;容易不理解这个类型。实际上:
ActivityResultLauncher<Intent>表示:
这是一个可以接收 Intent 参数的启动器。
因为StartActivityForResult()的输入类型就是Intent。
所以后面启动时:
launcher.launch(intent);相当于:
把 Intent 交给 Launcher
Launcher 再交给系统
系统启动目标 Activity
Launcher 本身不负责页面逻辑,它只是一个符合生命周期的启动入口。
启动目标 Activity
启动代码非常简单:
Intentintent=newIntent(this,SecondActivity.class);launcher.launch(intent);这里已经不需要:
startActivityForResult();只需要:
launch(intent);即可。
在第二个 Activity 中返回结果
创建 SecondActivity:
publicclassSecondActivityextendsAppCompatActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);findViewById(R.id.btnFinish).setOnClickListener(v->{Intentintent=newIntent();intent.putExtra("result","来自 SecondActivity 的数据");setResult(RESULT_OK,intent);finish();});}}这里和旧版写法几乎完全一样。返回结果依然使用:
setResult(resultCode,data);然后调用:
finish();回调中的 result 是什么
注册时, 这里的result类型是ActivityResult, 它主要有两个获取方法:
result.getResultCode()result.getData()resultCode
用于判断目标 Activity 是否成功返回。
最常见的是:
RESULT_OKRESULT_CANCELED因此通常会先判断:
if(result.getResultCode()==RESULT_OK)data
data本质上就是一个Intent。所以可以继续:
Stringtext=result.getData()!=null?result.getData().getStringExtra("result"):null;和普通 Intent 取值方式完全一致。
为什么 registerForActivityResult 要放在 onCreate 中
很多人第一次使用时会疑惑:为什么不能点击按钮时再注册?
button.setOnClickListener(v->{registerForActivityResult(...)});这样是不允许的。
Launcher 必须在Activity 生命周期开始阶段完成注册。
因为系统需要提前知道:
- 谁负责接收结果;
- Activity 重建后如何恢复回调。
所以官方要求:registerForActivityResult()必须在 Activity 或 Fragment 创建过程中调用。通常写在:
onCreate()数据是如何返回的
很多人会产生一个误解:是不是第二个 Activity 直接把变量传回来了?
其实不是。整个过程依然依赖Intent。
SecondActivity:
Intentintent=newIntent();intent.putExtra("result","Hello");setResult(RESULT_OK,intent);系统会保存这个 Intent。
finish(); 执行后,MainActivity 回调中:
result.getData()拿到的就是刚才那个 Intent。
putExtra()
↓
Intent
↓
setResult()
↓
系统保存
↓
ActivityResult.getData()
↓
getStringExtra()
和普通 Intent 传值原理是一致的。
Activity Result API 的完整流程
把前面的内容串起来,整个流程如下。
MainActivity:
publicclassMainActivityextendsAppCompatActivity{privateActivityResultLauncher<Intent>launcher;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);launcher=registerForActivityResult(newActivityResultContracts.StartActivityForResult(),result->{if(result.getResultCode()==RESULT_OK){Stringtext=result.getData()!=null?result.getData().getStringExtra("result"):null;Toast.makeText(this,text,Toast.LENGTH_SHORT).show();}});findViewById(R.id.btnOpen).setOnClickListener(v->{Intentintent=newIntent(this,SecondActivity.class);launcher.launch(intent);});}}SecondActivity:
publicclassSecondActivityextendsAppCompatActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);findViewById(R.id.btnFinish).setOnClickListener(v->{Intentintent=newIntent();intent.putExtra("result","来自 SecondActivity 的数据");setResult(RESULT_OK,intent);finish();});}}运行过程:
点击按钮
↓
launcher.launch(intent)
↓
打开 SecondActivity
↓
点击返回按钮
↓
setResult()
↓
finish()
↓
MainActivity 回调执行
↓
Toast 显示数据
整个过程中,不需要requestCode,也不需要onActivityResult()。
总结
Activity Result API 并没有改变 Activity 返回结果的本质,它仍然是Intent + setResult() + finish()。
真正变化的是:
- 使用
ActivityResultLauncher启动操作; - 使用
ActivityResultContract定义输入输出类型; - 使用注册回调代替
onActivityResult()。
相比旧方案,它最大的优势是代码更加模块化,与生命周期绑定更加安全。
后续学习中,你会发现 Android 调用系统相册、拍照、请求权限等功能,几乎都建立在 Activity Result API 的基础之上。理解本文的流程之后,再学习这些新版 API 会轻松很多。