0x1、引言
不是什么新玩意了,恰逢最近拆公司项目的BaseFragment时看到介个:
下划线?Deprecated?点开源码看下啥原因,有啥替代方案:
注释说这种写法out了,可在 ActivityResultContract
中传入一个 RequestMultiplePermissions
对象,并在回调中处理结果。除此之外,诸如 startActivityForResult()
、onActivityResult()
等都过时了。
搜了一波官方文档《获取 activity 的结果 》,没找到具体原因,笔者猜测官方旨在帮助开发者:减少样板代码、解耦。
以前跳转新页面回传数据,得经历这三步:
- 定义REQUEST_CODE,同一个页面有多个数据时,避免重复;
- 调用 startActivityForResult(Intent, REQUEST_CODE)
- 重写 onActivityResult(),判断requestCode和resultCode,拿到值后执行后续逻辑;
简易代码示例如下 :
新页面,一个简单的setResult,然后finish():
而使用 Activity Result API,你只需定义一个函数,然后launch()一下:
跳转页面不用动,可以看到:移除了onActivityResult()的重写,少写了一个REQUEST_CODE。看着好像是简洁了一些,对了网上一堆旧文章说要依赖activity-ktx和fragment-ktx,笔者使用1.4.0的activity和fragment包,发现已经内置这些东西了,可以不依赖,技术迭代飞快,建议读者使用时以官方文档为准。
0x2、原理浅探
Activity Results API的使用非常简单 (侧面说明封装得好),它由三个要素组成:启动器
+ 协定
+ 结果回调
。
① ActivityResultLauncher → 启动器
registerForActivityResult() 的返回值,用于:承载启动对象与返回对象
。
② ActivityResultContract → 协定/契约
第一个入参,协定的是:所需的输入类型
和 结果的输出类型
。
方法看着有点懵?没关系,找两个个具体实现类看看就知道了。
ActivityResultContracts
给我们提供了一些 常用的协定,拿来即用:
罗列下各自的作用 (直接看代码实现也能猜到干嘛的~):
StartActivityForResult()
→ 通用协定,不做任何转换,Intent作为输入,ActivityResult作为输出;StartIntentSenderForResult()
→ 内部Intent请求;RequestMultiplePermissions()
→ 请求一组权限;RequestPermission()
→ 请求单个权限;TakePicturePreview()
→ 调用MediaStore.ACTION_IMAGE_CAPTURE拍照,返回Bitmap图片;TakePicture()
→ 调用MediaStore.ACTION_IMAGE_CAPTURE拍照,并将图片保存在给定Uri,返回true表示保存成功;TakeVideo()
→ 调用MediaStore.ACTION_VIDEO_CAPTURE录制,并将视频保存在给定Uri,返回true表示保存成功;PickContact()
→ 调用通讯录APP获取联系人;GetContent()
→ 提示选择一条内容,返回一个通过ContentResolver#openInputStream(Uri)访问原生数据的Uri地址(content://形式) 。默认情况下,它增加了 Intent#CATEGORY_OPENABLE, 返回可以表示流的内容;GetMultipleContents()
→ 提示选择多条内容;OpenDocument()
→ 提示选择文档,返回Uri;OpenMultipleDocuments()
→ 提示用户选择多个文档,以List形式,返回他们的Uri;OpenDocumentTree()
→ 提示用户选择目录,返回Uri;CreateDocument()
→ 提示用户选择创建新文档的路径,返回已创建项目的Uri。
附:调用文件选择器,获取指定类型的文件,可在launch()方法里使用mimetype指定调用文件类型,文件mimetype对照表可参见:media-types