这是 Android 官方唯一推荐 的页面跳转 / 权限 / 拍照选择框架,彻底替代 startActivityForResult、onActivityResult、requestPermissions 那套老写法。
一、它是干嘛的?
替代:
- startActivityForResult()
- onActivityResult()
- requestPermissions()
优点:
- 生命周期安全(不会内存泄漏)
- 解耦(不用在 onActivityResult 里写一堆 if case)
- 链式调用、代码干净
- 官方永久推荐(老方法已废弃)
二、核心 3 个组件
- ActivityResultContract协议:你要传什么、返回什么(系统已提供很多默认实现,不用自己写)
- ActivityResultCallback回调:返回结果在这里接收
- ActivityResultLauncher启动器:真正发起跳转的对象
三、最常用的 2 个系统 Contract(90% 场景都用这俩)
1. StartActivityForResult()
跳转到另一个 Activity,接收返回结果
2. RequestPermissions()
请求权限
四、标准使用步骤(固定 3 步)
步骤 1:注册(onCreate 之前,直接定义全局变量)
kotlin
kotlin
// 跳转到 SecondActivity,并接收返回结果
private val startForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == RESULT_OK) {
val data = result.data
val name = data?.getStringExtra("name")
// 处理返回值
}
}
步骤 2:点击跳转
kotlin
kotlin
btnJump.setOnClickListener {
val intent = Intent(this, SecondActivity::class.java)
startForResult.launch(intent) // 启动
}
步骤 3:第二个页面返回数据
kotlin
scss
setResult(RESULT_OK, Intent().apply {
putExtra("name", "小明")
})
finish()
五、请求权限(超级简单)
kotlin
typescript
// 注册
private val requestPermission = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
if (isGranted) {
// 允许了
} else {
// 拒绝了
}
}
// 使用
requestPermission.launch(Manifest.permission.CAMERA)
兼容性结论(不需要再引入三方库)
✅ 完全兼容
- Android 4.1(API 16)+ 全部支持
- 无论目标版本是 Android 13 / 14 / 15 都没问题
- 无论你是 Activity / Fragment 都能用
- 无论屏幕旋转、系统重启,都能自动恢复回调,不会崩
✅ 为什么能全版本兼容?
因为:Activity Result API 是 AndroidX 库提供的兼容库不是系统原生 API,它内部自己做了全版本适配,你完全不用管版本差异。
六、请求多个权限
kotlin
ini
private val requestMultiPermission = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { result ->
val cameraGranted = result[Manifest.permission.CAMERA] ?: false
val locationGranted = result[Manifest.permission.ACCESS_FINE_LOCATION] ?: false
}
// 调用
requestMultiPermission.launch(
arrayOf(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION)
)
七、最关键知识点(必须懂)
1. registerForActivityResult 必须在 onCreate 之前注册
不能在点击事件里写!不能在延迟里写!必须作为成员变量直接初始化!
原因:系统需要在重建时恢复状态,必须提前注册。
2. 一个 launcher 对应一个功能
不要一个 launcher 乱用,会乱。规范:
- 跳转 A → 一个 launcher
- 跳转 B → 一个 launcher
- 申请权限 → 一个 launcher
3. 替代所有旧方案
- startActivityForResult → 废弃
- onActivityResult → 废弃
- requestPermissions → 废弃
全部用 Activity Result API 替代
八、最常用 Contract 大全
plaintext
scss
StartActivityForResult() → 跳转Activity
RequestPermission() → 申请单个权限
RequestMultiplePermissions() → 申请多个权限
TakePicturePreview() → 拍照(返回缩略图)
TakePicture() → 拍照(保存到Uri)
PickContact() → 选择联系人
GetContent() → 选择文件
CreateDocument() → 创建文件
OpenDocument() → 打开文件
九、为什么 Google 要推出它?(面试必问)
- 旧版 onActivityResult 代码耦合严重
- 多个请求时需要写 requestCode 判断,容易乱
- 重建时(旋转屏幕)容易丢失回调
- 不支持 DSL、不支持解耦
- Activity Result API 是生命周期安全的,提前注册,自动恢复
十一、你最需要的「万能模板」
跳转 Activity 模板(复制即用)
kotlin
kotlin
class MainActivity : AppCompatActivity() {
// 1. 注册
private val startForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == RESULT_OK) {
val name = result.data?.getStringExtra("name")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 2. 跳转
btnJump.setOnClickListener {
val intent = Intent(this, SecondActivity::class.java)
startForResult.launch(intent)
}
}
}