关注个人公众号 “安安安安卓” 学习更多知识java
很简单的一句话,ActivityResultContract
是用来在大部分场景中对startActivityForResult
和onActivityResult
进行替代的官方api
。api
ActivityResultContract
提供了一种类型安全的获取返回值的方式,好比拍照的api会返回泛型指定的bitmap。这避免了咱们手动处理onActivityResult回调致使的各类问题。浏览器
固然了我认为ActivityResultContract
最好的地方就是省心,尤为对于系统预置的集中ActivityResultContract
,只须要两步模板代码便可实现功能。安全
要实现自定义行为须要先自定义一个ActivityResultContract
类,定义以下:markdown
ActivityResultContract
类中有两个泛型,第一个泛型是I,第二个泛型是O,I表示输入也就是咱们启动activity须要putExtra的内容,O表述输入即onActivityResult返回的数据app
ActivityResultContract
有两个方法ide
createIntent
表示建立启动activity
的Intent
,其中方法的第二个参数可用于传给待启动activity
的参数parseResult
表示对返回数据的解析,方法的返回值就是registerForActivityResult
中回调的数据class CustomResultContracts : ActivityResultContract<Int, String>() {
override fun createIntent(context: Context, input: Int?): Intent {
return Intent(context, DestinishActivity::class.java).putExtra("input",input)
}
override fun parseResult(resultCode: Int, intent: Intent?): String {
return intent?.getStringExtra("data") ?: "未返回数据"
}
}
复制代码
private val customContract = registerForActivityResult(CustomResultContracts()){
getData(14).content="自定义Contracts返回数据:$it"
getData(14).notifyDataSetChange()
}
复制代码
customContract.launch(1)
复制代码
本例调用方法后会启动一个activity,新的activity点击返回数据将数据返回到列表中展现学习
注册代码
this
//注册结果监听
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == 3) {
showResult(it.data?.getStringExtra("data"))
}
}
复制代码
启动代码
spa
//启动activity,参数传intent
startForResult.launch(Intent(this@MainActivity, DestinishActivity::class.java))
复制代码
跳转到拍照页面,拍摄的照片会被保存到图库中
registerForActivityResult(ActivityResultContracts.TakePicturePreview()) {
getData(1).let {
it.notifyDataSetChange()
}
}
复制代码
模拟器录制不变,暂无效果图
TakePicture
方法会跳转到系统相机拍摄一张照片,返回bitmap,可是不会把图片保存到图库
private val takePreviewPic = registerForActivityResult(ActivityResultContracts.TakePicture()) {
logEE("搞预览图片成功")
}
复制代码
拍摄代码,须要说明的是拍摄视频完成后会须要等待较长时间,等待手机处理完视频的存储
private val captureVideo = registerForActivityResult(ActivityResultContracts.CaptureVideo()) {
logEE("拍摄视频成功:$it")
}
复制代码
模拟器录制不变,暂无效果图
很是简洁的方式实现权限申请
cameraPermission.launch(Manifest.permission.CAMERA)
复制代码
private val cameraPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
getData(3).apply {
content = "请求相机权限结果$it"
notifyDataSetChange()
}
}
复制代码
mutlePermission.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
)
复制代码
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
var result = ""
it.forEach { gaint ->
result += "获取${gaint.key} 权限 ${if (gaint.value) "成功" else "失败"}"
}
getData(4).content = result
getData(4).notifyDataSetChange()
}
复制代码
pickContact.launch(null)//参数传空
复制代码
private val pickContact = registerForActivityResult(ActivityResultContracts.PickContact()) {
logEE(it.toString())
getData(8).apply {
content = it.toString()
notifyDataSetChange()
}
}
复制代码
实现使用文件浏览器选择图片功能
getContent.launch("image/*")
复制代码
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) {
logEE(it.toString())
}
复制代码
由于模拟器没有图片可选,因此没有内容展现
2021/08/06 更新新内容以下
Fragment
中的使用和activity中是同样的,直接放参考代码吧
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<Button>(R.id.btn).setOnClickListener {
request.launch(Intent(activity, DestinishActivity::class.java))//启动新activity
}
}
/** * 注册结果监听 */
val request = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
logEE(it.data?.getStringExtra("data")!!)
}
复制代码
最终效果和activity是一致的