startActivityForResult废弃了,用Activity Result API吧
因为项目中突然需要用到两个activity之间进行数据交互,脑子里第一想法就是用EventBus来实现,但是需求仅仅只有2个activity之间进行交互(神奇的需求?),所以考虑几百年前用过的startActivityForResult来实现,但撸代码的时候发现,它过时了!!!
如果你将项目中的appcompat库升级到1.3.0或更高的版本,startActivityForResult()方法就已经显示被废弃了,因为项目中引入的就是1.3.0的
所以才发现过时的,如果版本低了,我还蒙在鼓里。
废弃了,自然有替代品。新欢胜旧爱,官网建议用Activity Result API来取代startActivityForResult了。
OK,先回顾下startActivityForResult的用法,它主要作用就是用于两个activity之间传递数据,例如:
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById<Button>(R.id.btn1).setOnClickListener {val intent = Intent(this, SecondActivity::class.java)val bundle=Bundle()bundle.putString("key","from MainActivity data")intent.putExtras(bundle)startActivityForResult(intent, 1)}}override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)when (requestCode) {1 ->if (resultCode == RESULT_OK) {val stringExtra = data?.getStringExtra("data")Log.e("TAG", "onActivityResult: $stringExtra")}}}
}
在MainActivity里通过点击一个按钮,往Bundle里添加数据,然后放到intent里,通过startActivityForResult向SecondActivity传递数据,并且重写了onActivityResult()方法去解析SecondActivity返回来的数据。
SecondActivity就稍微简单点了,先获取到MainActivity传递过来的数据,然后再点击一个按钮,发送新的数据返回给MainActivity。
class SecondActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_second)val extras = intent.extrasval data = extras?.getString("key")Log.e("SecondActivity", "onCreate: $data" )findViewById<Button>(R.id.btn).setOnClickListener {val intent = Intent()intent.putExtra("data", "data from SecondActivity")setResult(RESULT_OK, intent)finish()}}
}
以上代码应该没毛病,早几年每个项目百分百会用到的.
结果显而易见,从MainActivity点击按钮跳转到SecondActivity界面会打印
SecondActivity: onCreate: from MainActivity data
然后在SecondActivity点击按钮回到MainActivity打印
TAG: onActivityResult: data from SecondActivity
接着我们学习一下如何使用Activity Result API来实现同样的功能。
import androidx.activity.result.contract.ActivityResultContractsclass MainActivity : AppCompatActivity() {private val requestDataLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->if (result.resultCode == RESULT_OK) {val data = result.data?.getStringExtra("data")Log.e("TAG", "registerForActivityResult: $data")}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById<Button>(R.id.btn1).setOnClickListener {val intent = Intent(this, SecondActivity::class.java)val bundle = Bundle()bundle.putString("key", "from MainActivity data")intent.putExtras(bundle)requestDataLauncher.launch(intent)// startActivityForResult(intent, 1)}}
}
SecondActivity完全不用动,代码不用变。主要看下MainActivity的代码改动,移除了对onActivityResult()方法的重写,而是调用registerForActivityResult()方法来注册一个对Activity结果的监听。registerForActivityResult()方法接收两个参数,第一个参数是一种Contract类型,由于我们是希望从另外一个Activity中请求数据,因此这里使用了StartActivityForResult这种Contract。第二个参数是一个Lambda表达式,当有结果返回时则会回调到这里,然后我们在这里获取并处理数据即可。
@NonNull@Overridepublic final <I, O> ActivityResultLauncher<I> registerForActivityResult(@NonNull ActivityResultContract<I, O> contract,@NonNull ActivityResultCallback<O> callback) {return registerForActivityResult(contract, mActivityResultRegistry, callback);}
从源码可以看到registerForActivityResult返回的是ActivityResultLauncher对象,
可以看到该对象当中有launch()方法可以用于去启用Intent。所以我们的代码中就能使用
requestDataLauncher.launch(intent)去进行调整,从而代替startActivityForResult()方法。
以上代码运行效果和startActivityForResult()的完全一致。如果说单纯从数据跳转传递来讲,这也差不多呀。没啥优势的。
再来个例子,多任务之间进行区分。
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById<Button>(R.id.btn1).setOnClickListener {val intent = Intent(this, SecondActivity::class.java)val bundle = Bundle()bundle.putString("key", "from MainActivity data1")intent.putExtras(bundle)startActivityForResult(intent, 1)}findViewById<Button>(R.id.btn2).setOnClickListener {val intent = Intent(this, ThreeActivity::class.java)val bundle = Bundle()bundle.putString("key", "from MainActivity data2")intent.putExtras(bundle)startActivityForResult(intent, 2)}}override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)when (requestCode) {1 -> {if (resultCode == RESULT_OK) {val stringExtra = data?.getStringExtra("data")Log.e("TAG", "onActivityResult: 1$stringExtra")}}2 ->if (resultCode == RESULT_OK) {val stringExtra = data?.getStringExtra("data")Log.e("TAG", "onActivityResult: 2 $stringExtra")}}}
}
通过设置不同的requestCode值来区分传递不同界面的数据。因此获取返回的数据时也要在onActivityResult()方法当中,再对requestCode进行判断。这种传统的写法,大家应该都很熟悉,也见得多了,那么看下Activity Result API是怎么实现这种多任务的数据传递接收的
class MainActivity : AppCompatActivity() {private val requestDataOneLauncher =registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->if (result.resultCode == RESULT_OK) {val data = result.data?.getStringExtra("data")Log.e("TAG", "registerForActivityResult:one $data")}}private val requestDataTwoLauncher =registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->if (result.resultCode == RESULT_OK) {val data = result.data?.getStringExtra("data")Log.e("TAG", "registerForActivityResult:two $data")}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById<Button>(R.id.btn1).setOnClickListener {val intent = Intent(this, SecondActivity::class.java)val bundle = Bundle()bundle.putString("key", "from MainActivity data1")intent.putExtras(bundle)requestDataOneLauncher.launch(intent)}findViewById<Button>(R.id.btn2).setOnClickListener {val intent = Intent(this, SecondActivity::class.java)val bundle = Bundle()bundle.putString("key", "from MainActivity data2")intent.putExtras(bundle)requestDataTwoLauncher.launch(intent)}}
}
通过ActivityResultLauncher不同对象处理不同的任务数据,无需借助requestCode数字来判断,万一数字多了不对,还容易出错。所以Activity Result API存在是有一定的合理性的。
startActivityForResult废弃了,用Activity Result API吧相关推荐
- Activity Result API详解,是时候放弃startActivityForResult了
本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每个工作日都有文章更新. 如果你将项目中的appcompat库升级到1.3.0或更高的版本,你会发现startActi ...
- Android MVVM框架搭建(十)Hilt、ViewBinding、Activity Result API
Android MVVM框架搭建(十)Hilt.ViewBinding.Activity Result API 前言 正文 一.依赖 二.Hilt使用 1. Hilt 应用类 2. ViewModel ...
- activity 点击后传递数据给fragment_Fragment 新特性 : Fragment Result API 使用以及源码分析
原标题: Android Fragments: Fragment Result 原文地址: https://proandroiddev.com/android-fragments-fragment-r ...
- 关于android开发中startActivityForResult废弃的替换方法调用
关于android开发中startActivityForResult废弃的替换方法调用 在最近一段时间中,能在开发时看到在android studio中,startActivityForResult方 ...
- 以回调形式使用startActivityForResult方法,并解决Activity被回收的问题
前言 之前写过一篇文章写一个逻辑清晰的startActivityForResult(),拒绝来回扒拉代码,写了使用回调形式使用startActivityForResult方法,配合Kotlin的语法, ...
- 谷歌支付:In-app billing error: Null data in IAB activity result (-1002 )
今天测试谷歌支付又遇到一个新坑,在小米手机进行的测试调用谷歌支付的时候支付弹窗一直不出来,打印结果显示 In-app billing error: Null data in IAB activity ...
- Android:通过startActivityForResult方法来得到Activity的回传值
在一些情况下,我们通过 A activity跳转到 B activity上,这时希望 A activtiy能从 B activity上得到一些返回值,这个时候我们就不能使用startActivity方 ...
- startActivityForResult被标记为弃用后,如何优雅的启动Activity?
文章目录 一.如何解决 startActivityForResult 被弃用? 二.ActivityResultContract 该如何使用? 三.但是......我就想简单的使用startActiv ...
- Android活动返回不在再支持startActivityForResult()后的处理方法
实现活动之间的交互,并返回上个活动,传统的方法是利用startActivityForResult启动活动,并在onActivityResult函数中处理返回上一个活动的数据及其他的处理.具体代码的做法 ...
最新文章
- 自定义函数_自定义函数,让你的表格为所欲为
- Android --- 夜神模拟器中没有图片怎么办?夜神模拟器中怎么导入图片?
- html5添加到安卓桌面图标,Android向桌面添加快捷方式,使其指向特定的网页
- redis 值字符串前面部分乱码_StringBoot 整合Redis解决存储乱码(通过StringRedisSerializer来进行序列化)...
- 无服务器安全性:将其置于自动驾驶仪上
- proteus如何添加stm32_新手入门轻松掌握 STM32 串口应用
- W-Cms XSS和遍历目录漏洞
- 清理电脑文件夹中的Thumbs.db文件
- [云盘]共享文件列表
- 面试精选-solr篇
- 万物皆可GAN之pytorch和神经网络
- 什么是好用的身份证实名认证api接口?其应用场景有哪些?
- 用友NC单据UI基本代码示例
- Hello hello ~
- 在栈中压入一个字符串c语言,一 道C语言试题的探讨
- About 不以物喜 不以己悲
- 关闭selinux的方法汇总
- 2021年技术自媒体经验分享 —— 开始尝试认真做 CSDN 的一年后的复盘
- RHCE之路--15更新 Ansible 库的密钥
- 在不交智商税的情况下,如何判断一场知乎live的质量?