原文地址:Jetpack架构组件学习(3)——Activity Results API使用 - Stars-One的杂货小窝

技术与时俱进,页面跳转传值一直使用的是startActivityForResult方法,如今有了新的API实现方式,学习并稍微总结下

startActivityForResult复习

MainActivity代码:

Main2Activity代码:

效果:

上面的代码应该是比较基础的代码,这里我就不再赘述了

主要说些缺点

所有逻辑都在onActivityResult()方法里进行判断,根据requestCoderesultCode进行判断

如果单个还好说,但是如果有多个的,就会看见onActivityResult()里一堆的if逻辑,阅读起来就十分繁琐,且维护困难

谷歌官方也是考虑到了这个,于是便是在新版本推出了个Activity Results API去替代了上面所述的方式,下面就介绍下如何使用

简单使用

1.引入依赖

首先,需要我们引入依赖:

implementation 'androidx.appcompat:appcompat:1.3.1'

PS: 请使用1.3.1以上版本,低版本没有这个枚举类ActivityResultContracts

我们先以上面的例子,使用Activity Results API

Main2Acitivity代码不用动,我们只需要调整MainActivity文件里代码,如下所示:

2.创建契约

val contract = ActivityResultContracts.StartActivityForResult()

contract变量的对象类名为ActivityResultContract

ActivityResultContracts相当于一个枚举类,是谷歌官方贴心封装的,里面提供了一些常用的ActivityResultContract类对象供我们使用

像拍照,申请权限的等操作,从代码提示就可以看到了,如下图所示:

这里我们选用StartActivityForResult(),字面意思应该很好理解,就是应用在就是页面跳转并返回数据的情景

PS:根据我们选用的ActivityResultContracts,会影响第4步中的传参类型

下面补充下对应的选择说明:

  • StartActivityForResult: 通用的Contract,不做任何转换,Intent作为输入,ActivityResult作为输出,这也是最常用的一个协定。
  • CreateDocument: 提示用户选择一个文档,返回一个(file:/http:/content:)开头的Uri。
  • GetContent: 提示用选择一条内容,返回一个通过ContentResolver#openInputStream(Uri)访问原生数据的Uri地址(content://形式) 。默认情况下,它增加了 Intent#CATEGORY_OPENABLE, 返回可以表示流的内容。
  • GetMultipleContents:获取多条内容
  • OpenDocument: 提示用户选择指定类型文件(输入参数为mimeType),返回用户所选文件Uri
  • OpenDocumentTree: 提示用户选择一个目录,并返回用户选择的作为一个Uri返回,应用程序可以完全管理返回目录中的文档。
  • OpenMultipleDocuments: 提示用户选择文档(可以选择多个),分别返回它们的Uri,以List的形式。
  • PickContact: 从通讯录APP获取联系人
  • RequestMultiplePermissions:用于请求一组权限
  • RequestPermission: 用于请求单个权限
  • TakePicturePreview: 调用MediaStore.ACTION_IMAGE_CAPTURE拍照,返回值为Bitmap图片
  • TakePicture: 调用MediaStore.ACTION_IMAGE_CAPTURE拍照,并将图片保存到给定的Uri地址,返回true表示保存成功。
  • TakeVideo: 调用MediaStore.ACTION_VIDEO_CAPTURE 拍摄视频,保存到给定的Uri地址,返回一张缩略图。

具体参数和说明可以使用的时候查看文档哦~

实际上,如果上面所列还不能满足我们的需求,那么我们也可以自定义契约操作,在文章下面再进行补充说明,这里就先不进行扩展了

3.建立契约(注册Contact)

//注册ActivityResultContract
val myLauncher = registerForActivityResult(contract){
if (it.resultCode==2) {
val data = it.data
if (data != null) {
val resultData = data.getStringExtra("mydata")
Toast.makeText(this, resultData, Toast.LENGTH_SHORT).show()
}
}
}

使用Activity类中registerForActivityResult()方法,进行契约的注册,实际上就是相当于注册了一个监听,之后从Main2Activity页面返回MainActivity页面,会回调这个里面的方法

注意: 这里有个变量myLauncher,之后第三步需要使用

4.发起页面跳转

val intent = Intent(this, Main2Activity::class.java)
myLauncher.launch(intent)

调用myLauncher对象的launch()方法,将intent对象传递即可实现页面跳转的操作

PS: 这里还是在按钮的点击事件里,方便阅读就省略了

之后从Main2Activity页面返回之后,会回调第二步中的操作,效果与上面的动图演示一致,这里就不再重新贴个图了

自定义ActivityResultContract

ActivityResultContract实际上还包含两个泛型,完整应该是这样ActivityResultContract<I,O>

  • I为input的意思,意为输入参数类型
  • O为output的意思,意为输出参数类型

ActivityResultContract<I,O>是个抽象类,我们想要实现自定义,那么就直接继承它

class MyContract: ActivityResultContract<String, String>() {

    override fun createIntent(context: Context, input: String?): Intent {
//这里input的类型,就是上文说到的I
} override fun parseResult(resultCode: Int, intent: Intent?): String {
//这里方法返回的结果类型,就是上文说到的O } }

继承发现,需要我们实现两个方法,createIntent()parseResult()

一眼过去其实很好理解,createIntent()就是创建一个intent对象,调用launch()方法的时候(上面使用的第4步操作),里面就会根据此intent进行页面的跳转操作

parseResult()方法,则是建立契约那步,里面回调的数据类型

我们以上面的例子,发现我们还得声明一个Intent对象传递,以及回传的时候还得通过intent对象去获取数据,有些繁琐,有些代码可以封装成通用的

照着这个想法,我们可以实现一个自定义ActivityResultContract,传递页面参数即可拿到Main2Activity返回的数据,代码如下所示:

class MyContract: ActivityResultContract<KClass<out Activity>, String>() {

    override fun parseResult(resultCode: Int, intent: Intent?): String? {
if (resultCode == 2 && intent!=null) {
return intent.getStringExtra("mydata")
}
return null
} override fun createIntent(context: Context, input: KClass<out Activity>?): Intent {
val intent = Intent(context,input?.java)
return intent
} }

使用:

//1.创建契约
val contract = MyContract() //2.注册ActivityResultContract
val myLauncher = registerForActivityResult(contract){
Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
} btnGo.setOnClickListener {
//2.发起页面跳转
myLauncher.launch(Main2Activity::class)
}

当然,这里还可以优化,如我们让MyContract多个构造函数,这样取值的key也可以通过此进行定义

class MyContract(val key: String) : ActivityResultContract<KClass<out Activity>, String>() {

    override fun parseResult(resultCode: Int, intent: Intent?): String? {
if (resultCode == 2 && intent != null) {
return intent.getStringExtra(key)
}
return null
} override fun createIntent(context: Context, input: KClass<out Activity>?): Intent {
val intent = Intent(context, input?.java)
return intent
} }

使用:

//创建契约里传参即可
val contract = MyContract("mydata")

参考

Jetpack架构组件学习(3)——Activity Results API使用的更多相关文章

  1. Jetpack架构组件学习(1)——LifeCycle的使用

    原文地址:Jetpack架构组件学习(1)--LifeCycle的使用 | Stars-One的杂货小窝 要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 最近 ...

  2. Jetpack架构组件学习(2)——ViewModel和Livedata使用

    要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 原文地址:Jetpack架构组件学习(2)--ViewModel和Livedata使用 | Stars-One ...

  3. Jetpack架构组件学习(4)——APP Startup库的使用

    最近在研究APP的启动优化,也是发现了Jetpack中的App Startup库,可以进行SDK的初始化操作,于是便是学习了,特此记录 原文:Jetpack架构组件学习(4)--App Startup ...

  4. Jetpack 架构组件 Room 数据库 ORM MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  5. Jetpack 架构组件 LiveData ViewModel MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  6. Jetpack 架构组件 Lifecycle 生命周期 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  7. Android 架构:Android Jetpack 架构组件的学习和分析

    参考:https://mp.weixin.qq.com/s/n-AzV7Ke8wxVhmC6ruUIUA 参考:https://jekton.github.io/2018/06/30/android- ...

  8. Android Jetpack 架构组件最佳实践之“网抑云”APP

    背景 近几年,Android 相关的新技术层出不穷.往往这个技术还没学完,下一个新技术又出来了.很多人都是一脸黑人问号? 不少开发者甚至开始哀嚎:"求求你们别再创造新技术了,我们学不动了!& ...

  9. Android 四大组件学习之Activity六

    本节学习Activity的状态保存与恢复. 先用样例開始: 布局文件主要是实现例如以下.大家自行编写 Activity逻辑代码: public class FiveActivity extends A ...

随机推荐

  1. js获取url查询字符串参数

    最近看js高级程序设计 对其中查询字符串参数的获得重新写了,当传递一个完整的URL的时候对查询字符串的提取 function getQueryArgs(){ var qs = (location.se ...

  2. 【代码大全2 学习笔记】ADT 抽象与封装

    ADT abstract data type 抽象数据类型 要理解面向对象编程,就要先理解ADT这个概念.不懂ADT的程序员开发出来的类只是名义上的"类"而已--只是单纯的把一些相 ...

  3. Python入门-变量与命名

    在上一篇中,我们定义了很多变量,变量格式是啥?变量名字可以随意么?有啥命名规范么?下面细讲 变量格式 变量名称 = 常量 把常量赋值给变量的过程,就是定义变量. 定义变量 Python中的变量不需要声 ...

  4. matplotlib---Annotation标注

    import numpy as np import matplotlib.pyplot as plt x = np.linspace(-3, 3, 50) y = 2 * x + 1 plt.figu ...

  5. 性能优化之html、css、js三者的加载顺序

    前言 我们知道一个页面通常由,html,css,js三部分组成,一般我们会把css文件放在head头部加载,而js文件则放在页面的最底部加载,想要知道为什么大家都会不约而同的按照这个标准进行构建页面, ...

  6. re模块、collections模块、time模块、datetime模块

    正则表达式之re模块 re.findall用法(重要) re.findall( '正则表达式' , '待匹配的字符' ) 找出所有的目标字符,用列表的形式展现,如果找不到返回空列表. import r ...

  7. jquery 日期插件datePicker使用

    1.将下载下来的DatePicker压缩包解压后整个放入项目中,不可只引入js和css 2.在html中指定input位置加上class="Wdate"(默认样式不加也可正常显示) ...

  8. zabbix监控SSL证书有效期

    想给公司网站加上证书的监控,发现agent无此监控项.科普之后发现需要自行添加脚本以及一些操作. 环境信息 系统版本: Ubuntu20.04 zabbix server版本:5.4 (这个自定义貌似 ...

  9. Java学习day13

    泛型类格式: 修饰符 class 类名<类型>{ } 常用T.E.K.V等形式的参数表示泛型 使用方式与C++的类模板相似,在创建对象时要明确数据类型 泛型方法定义格式: 修饰符<类 ...

  10. this的指向问题及改变this指向

    概念: this是运行环境下的一个系统变量, 由于this在不同的执行环境下有不同的值, 所以在使用this时,多加注意 (使用this之前,先打印) 1,在全局作用域下,this默认指向window ...