放弃 startActivityForResult,Activity Result API 优雅使用

news2024/12/26 23:20:19

放弃 startActivityForResult,Activity Result API 优雅使用

Activity Result API 是 androidx 中的一个新 api,旨在替代原有的 startActivityForResult 方法,用于在两个 Activity 或 Fragment 交换数据、获取返回结果。

过去如果 Activity A 想获取 Activity B 的结果时,需要调用 startActivityForResult 启动 Activity 并重写 onActivityResult 方法获取返回值,这种写法让数据返回的处理逻辑和 Activity 强耦合在一起,代码复用不方便,可读性也很低。

//1.启动Activity
startActivityForResult(intent, 111)

//2.接收返回值:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == 111) {
        when (resultCode) {
            1 ->  { ... }
            2 ->  { ... }
        }
    }
}

目前 startActivityForResult 方式已被标为废弃方法,Google 推荐使用 Activity Result API 来进行 Activity 或 Fragment 数据交换,这一改变主要是为了简化代码结构,提高代码的重用性和可维护性。以下是对Activity Result API的详细介绍:

Activity Result API的核心组件

  • ActivityResultContract<I, O>:协议,定义了数据类型、如何传递数据和处理返回数据。ActivityResultContract 是一个抽象类,可以继承它来创建自己的协议。泛型 I 是输入类型,O 是输出类型,如果不需要任何输出可以应用 Unit。

  • ActivityResultCallback<O>:返回结果监听,通过该回调获取返回结果。

  • registerForActivityResult ,启动器注册方法,定义在 ComponentActivity 和 Fragment 中,注册协议并返回启动器。

    该方法需要注意调用位置,调用过晚会抛出异常:

    • Activity:LifecycleOwners must call register before they are STARTED.
    • Fragment:Fragments must call registerForActivityResult() before they are created (i.e. initialization, onAttach(), or onCreate())."
  • ActivityResultLauncher:启动器,调用它的 launch 方法来启动页面跳转,作用相当于原来的 startActivity()。

ActivityResultContract的类型

系统提供了几种常用的 ActivityResultContract 类型,如无特殊需求可以直接使用:

  • StartActivityForResult:通用 Contract,内部未做任何转换。输入 Intent,输出 ActivityResult,是最常用的。

    class StartActivityForResult : ActivityResultContract<Intent, ActivityResult>() {
        override fun createIntent(context: Context, input: Intent):Intent = input
        override fun parseResult(resultCode: Int,intent: Intent?):ActivityResult = ActivityResult(resultCode, intent)
    }
    
  • RequestPermission:请求单个权限。输入类型 String,具体权限;输出类型 Boolean,权限申请结果。

  • RequestMultiplePermissions:请求一组权限。输入类型 Array,权限组;输出类型 Map<String, Boolean> 权限申请结果。

  • TakePicture: 调用 MediaStore.ACTION_IMAGE_CAPTURE 拍照,输入类型 Uri,照片存储地址;输出类型 Boolean 拍照结果。

  • TakePicturePreview:调用 MediaStore.ACTION_IMAGE_CAPTURE 拍照,输入类型 Void? ,输出类型 Bitmap,图片。

  • TakeVideo:调用 MediaStore.ACTION_VIDEO_CAPTURE 拍摄视频,输入类型 Uri,视频存储地址;输出类型 Bitmap?,缩略图。

  • PickContact:选择联系人。

  • GetContent:获取用户内容,输入类型 String,过滤的mime 类型(如image/*);输出类型 Uri,内容位置。

  • CreateDocument:创建文档,输入类型 String,新文件的建议名称;输出类型 Uri。

  • OpenDocument:选择单个文档,输入类型 Array,过滤的mime类型;输出类型 Uri。

  • OpenMultipleDocuments:选择多个文档,输入类型 Array, 过滤的mime类型;输出类型 List。

  • OpenDocumentTree:选择一个目录,输入类型 Uri?,可选的初始目录;输出类型 Uri?。

使用步骤

举个例子,FirstActivity -> SecondActivity,需要 FirstActivity 将数据传递给 SecondActivity,SecondActivity 处理完数据后将数据回传给 FirstActivity。

  1. FirstActivity 中需要 调用 registerForActivityResult 方法注册启动器,参数一是启动协议,这里直接用内置的 StartActivityForResult;参数二是数据回调监听,在此处理数据返回逻辑。

  2. 使用启动器的 launch 方法进行页面跳转,Activity A 中代码如下:

    class FirstActivity : AppCompatActivity() {
        lateinit var button: Button
    
        //1.注册启动器
        private val launcher: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult(), object: ActivityResultCallback<ActivityResult> {
            override fun onActivityResult(result: ActivityResult) {
                //3.处理SecondActivity返回数据
                if (result.resultCode == RESULT_OK) {
                    val content = result.data?.getStringExtra("RESULT_CONTENT")
                    Log.d("baize_", "FirstActivity get result content:${content}}")
                }
            }
        })
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.first_activity)
            button = findViewById(R.id.button)
            button.setOnClickListener {
                //2.启动Activity B,并传递数据
                val intent = Intent(this, SecondActivity::class.java).apply {
                    putExtra("INPUT_CONTENT", "custom data...")
                }
                launcher.launch(intent)
            }
        }
    }
    
  3. SecondActivity 中按传统方式接收和返回数据:

    class SecondActivity : AppCompatActivity() {
        lateinit var button: Button
        
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_second)
            button = findViewById(R.id.button)
            //1.获取FirstActivity传递来的数据
            val content = intent.getStringExtra("INPUT_CONTENT")
            Log.d("baize_", "SecondActivity get input content:${content}}")
    
            button.setOnClickListener {
                //2.设置返回数据
                val intent = Intent().apply {
                    putExtra("RESULT_CONTENT", editText.text.toString())
                }
                setResult(RESULT_OK, intent)
                finish()
            }
        }
    }
    

自定义协议

继续上面的例子,如果不希望每次跳转都书写同样的 Intent 解析代码,就可以自定义启动器将模板代码封装到里面:

自定义 Contract:

class CustomContract: ActivityResultContract<String, String?>() {
    override fun createIntent(context: Context, input: String): Intent {
        val intent = Intent(context, SecondActivity::class.java)
        intent.putExtra("input", input)
        return intent
    }

    override fun parseResult(resultCode: Int, intent: Intent?): String? {
        return if (resultCode == RESULT_OK) { intent?.getStringExtra("RESULT_CONTENT") } else null
    }
}

使用时:

//1.注册启动器
private val launcher: ActivityResultLauncher<String> = registerForActivityResult(CustomContract(), object: ActivityResultCallback<String?> {
    override fun onActivityResult(result: String?) {
        //3.直接处理返回值
        Log.d("baize_", "activity 1 get result content:${result}}")
    }
})

//2.启动页面,直接传入String值
launcher.launch("custom data...")

最后效果:

总结

使用 Activity Result API 相比传统的 startActivityForResult()onActivityResult() 方法,具有以下优点:

  • 代码更加简洁:通过将结果处理逻辑与 Activity 的生命周期解耦,使得代码更加简洁易读。
  • 提高重用性:自定义的 ActivityResultContract 可以在多个地方重复使用,提高代码的重用性。
  • 易于维护:减少了 onActivityResult 方法的嵌套和耦合,使得代码更加易于维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2170179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

了解独享IP的概念及其独特优势

在网络世界中&#xff0c;IP地址是用来识别和定位设备的标识符。独享IP是一种服务模式。使用代理服务器时&#xff0c;用户拥有一个不与其他用户共享的专用独立IP地址。与共享IP相比&#xff0c;独享IP为用户提供了更高的独立性和隐私保护。下面详细介绍独享IP的定义、工作原理…

OJ在线评测系统 后端 代码沙箱原生实现 初始化项目

代码沙箱Java原生实现 之前我们完成了快速的前端页面开发 重点是在后端 历史问题修复 Java原生代码沙箱实现 docker代码沙箱实现 解决历史遗留问题 代码编辑器切换语言失败 监听language属性 动态更改编辑器的语言 我们在这里实现的是一个线程形式的监听 watch(() > …

总结拓展十一:S4 HANA和ECC区别

第一节 S/4 HANA系统简介 SAP系统的产品线 R/1版本——主要财务模块R/3版本——基本实现全模块ECC6.0——2005年推出&#xff08;ECC是2004年推出&#xff09;HANA——数据库产品——属于内存数据库BW on HANA——HANA与数据分析相结合 拓展&#xff1a; 数据库类型&#x…

易盾滑块验证码

前言 这玩意我就搞定get请求和check请求&#xff0c;那个b接口的d参数还是有点问题&#xff0c;还有就是b接口的返回参数怎么用&#xff0c;是不是只是加了cookie我也不确定&#xff0c;所以有高手的话希望可以指导一下。我的虽然能够成功&#xff0c;但是只有前2次成功&#x…

ARM V8 A32常用指令集

文章目录 1. 算术指令1.1 加法命令ADD\ADDS1.2 带进位加法命令ADC\ADCS1.3减法命令SUB\SUBC1.4带借位减法命令SBC\SBCS 2.逻辑运算指令2.1逻辑与指令AND、ANDS2.2位清零指令BIC2.3逻辑或指令ORR\ORRS2.4逻辑异或指令2.5 逻辑左移LSL2.6逻辑右移LSR 3.比较指令3.1直接比较指令CM…

2024年华为杯研究生数学建模竞赛C题 波形机理建模+GBDT 完整文章代码|进阶可视化

2024年华为杯研究生数学建模竞赛C题 波形机理建模GBDT 完整文章代码|进阶可视化 全部问题已经更新完成&#xff0c;可视化图表20余张&#xff0c;代码量千余行&#xff0c;实在累到了… 由于篇幅原因&#xff0c;此处放出部分内容供参考~ 完整内容可以从底部名片的群中获取~ …

vue3监听子组件的生命周期

1.Vue3使用vue&#xff0c;vue2使用hook template:<compG vue:mounted"doSomething"></compG>script://监听子组件生命周期let doSomething (e: any) > {console.log("没有啊11", e);}; 2.打印结果

昇思MindSpore进阶教程--轻量化数据处理

大家好&#xff0c;我是刘明&#xff0c;明志科技创始人&#xff0c;华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享&#xff0c;如果你也喜欢我的文章&#xff0c;就点个关注吧 正文开始 在资源条件允许的情况下&#…

【趣学Python算法100例】数制转换

问题描述 给定一个M进制的数x&#xff0c;实现对x向任意一个非M进制的数的转换。 问题分析 要搞定这道题&#xff0c;关键在于学会不同数制之间的转换&#xff0c;主要是二进制、八进制、十六进制和十进制这几种。理解下面这几个概念非常重要&#xff1a; 基数&#xff1a;…

Go基础学习06-Golang标准库container/list(双向链表)深入讲解;延迟初始化技术;Element;List;Ring

基础介绍 单向链表中的每个节点包含数据和指向下一个节点的指针。其特点是每个节点只知道下一个节点的位置&#xff0c;使得数据只能单向遍历。 示意图如下&#xff1a; 双向链表中的每个节点都包含指向前一个节点和后一个节点的指针。这使得在双向链表中可以从前向后或从后…

Docker仓库搭建

目录 一、Docker Hub 二、私有Registry仓库搭建 1、下载并开启仓库镜像registry 2、Registry加密传输 3、建立一个registry仓库 4、为客户端建立证书 5、测试 6、为仓库建立登录认证 三、Harbor仓库搭建 Docker 仓库&#xff08;Docker Registry&#xff09; 是用于存…

8种数值变量的特征工程技术:利用Sklearn、Numpy和Python将数值转化为预测模型的有效特征

特征工程是机器学习流程中的关键步骤&#xff0c;在此过程中&#xff0c;原始数据被转换为更具意义的特征&#xff0c;以增强模型对数据关系的理解能力。 特征工程通常涉及对现有数据应用转换&#xff0c;以生成或修改数据&#xff0c;这些转换后的数据在机器学习和数据科学的…

书生大模型实战营学习[9] OpenCompass 评测 InternLM-1.8B 实践

准备工作 打开开发机&#xff0c;选择cuda11.7环境&#xff0c;A100选择10%&#xff0c;点击创建&#xff0c;然后进入开发机即可&#xff0c;和之前的操作一样。接下来创建环境&#xff0c;下载必要的依赖包 conda create -n opencompass python3.10 conda install pytorch2…

什么是网络安全自动化以及优势与挑战

目录 网络安全自动化的工作原理 网络安全自动化的好处 增强的安全功能 改善表现和姿势 降低安全成本 简化的安全合规性和审计 更好的端点管理 网络安全自动化的挑战 耗时且容易出错的安全流程 可见性降低&#xff0c;风险和成本增加 合规管理 有用的网络安全自动化…

2024年合肥市职业院校技能大赛(中职组)赛 网络安全 竞赛样题

2024年合肥市职业院校技能大赛(中职组)赛 网络安全 竞赛样题 (总分100分) 培训、环境、资料、考证 公众号&#xff1a;Geek极安云科 网络安全群&#xff1a;624032112 网络系统管理群&#xff1a;223627079 网络建设与运维群&#xff1a;870959784 极安云科专注于技能提升&am…

基于nodejs+vue的旅游管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

Docker启动失败,Failed to start docker,只需三个步骤,看我怎么搞定它!

在项目部署上线的时候 1打开hyper-v虚拟机 怎么打开呢&#xff1f; 命令提示符输入control,点击回车&#xff0c;打开控制面板&#xff0c;打开“程序和功能”&#xff0c;“启用和关闭windows功能”&#xff0c;选择Hyper-v&#xff0c;勾选下面的每一项内容。完成之后又点…

机器学习-模型集成

文章目录 模型集成为什么要集成&#xff1f;模型集成要解决的问题主要的集成思想 Committees多个模型的结果进行融合。BaggingBagging 特点 BoostingAdaBoost算法过程 GBDT负梯度拟合 XGBoostXGBoost 参数通用参数booster 参数学习目标参数 模型保存 模型集成 三个臭皮匠顶一个…

结构连接能否成为精神病早期的功能预后标志?

TLDR: 该研究发现精神病首次发作的患者&#xff08;未经药物治疗&#xff09;脑部存在广泛的结构连接减少&#xff0c;尤其是前额叶-纹状体-丘脑系统的连接异常。基线时的脑部结构连接可以有效预测患者12个月后的功能恢复情况。研究表明&#xff0c;脑部结构连接的减少可能与精…

【游戏策划 还能这么玩】

长期陷入低迷的桌游圈最近重新焕发出希望的光芒。由腾讯和网易离职的策划及美术团队开发的桌游《王冠继承者之战》在一小时内众筹金额突破20万。 对于游戏策划者来说&#xff0c;不妨拓展思路&#xff0c;将目光转向尚未充分挖掘的桌游市场&#xff0c;那里可能蕴藏着让人意想…