因为项目中突然需要用到两个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吧相关推荐

  1. Activity Result API详解,是时候放弃startActivityForResult了

    本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每个工作日都有文章更新. 如果你将项目中的appcompat库升级到1.3.0或更高的版本,你会发现startActi ...

  2. Android MVVM框架搭建(十)Hilt、ViewBinding、Activity Result API

    Android MVVM框架搭建(十)Hilt.ViewBinding.Activity Result API 前言 正文 一.依赖 二.Hilt使用 1. Hilt 应用类 2. ViewModel ...

  3. activity 点击后传递数据给fragment_Fragment 新特性 : Fragment Result API 使用以及源码分析

    原标题: Android Fragments: Fragment Result 原文地址: https://proandroiddev.com/android-fragments-fragment-r ...

  4. 关于android开发中startActivityForResult废弃的替换方法调用

    关于android开发中startActivityForResult废弃的替换方法调用 在最近一段时间中,能在开发时看到在android studio中,startActivityForResult方 ...

  5. 以回调形式使用startActivityForResult方法,并解决Activity被回收的问题

    前言 之前写过一篇文章写一个逻辑清晰的startActivityForResult(),拒绝来回扒拉代码,写了使用回调形式使用startActivityForResult方法,配合Kotlin的语法, ...

  6. 谷歌支付:In-app billing error: Null data in IAB activity result (-1002 )

    今天测试谷歌支付又遇到一个新坑,在小米手机进行的测试调用谷歌支付的时候支付弹窗一直不出来,打印结果显示 In-app billing error: Null data in IAB activity ...

  7. Android:通过startActivityForResult方法来得到Activity的回传值

    在一些情况下,我们通过 A activity跳转到 B activity上,这时希望 A activtiy能从 B activity上得到一些返回值,这个时候我们就不能使用startActivity方 ...

  8. startActivityForResult被标记为弃用后,如何优雅的启动Activity?

    文章目录 一.如何解决 startActivityForResult 被弃用? 二.ActivityResultContract 该如何使用? 三.但是......我就想简单的使用startActiv ...

  9. Android活动返回不在再支持startActivityForResult()后的处理方法

    实现活动之间的交互,并返回上个活动,传统的方法是利用startActivityForResult启动活动,并在onActivityResult函数中处理返回上一个活动的数据及其他的处理.具体代码的做法 ...

最新文章

  1. 自定义函数_自定义函数,让你的表格为所欲为
  2. Android --- 夜神模拟器中没有图片怎么办?夜神模拟器中怎么导入图片?
  3. html5添加到安卓桌面图标,Android向桌面添加快捷方式,使其指向特定的网页
  4. redis 值字符串前面部分乱码_StringBoot 整合Redis解决存储乱码(通过StringRedisSerializer来进行序列化)...
  5. 无服务器安全性:将其置于自动驾驶仪上
  6. proteus如何添加stm32_新手入门轻松掌握 STM32 串口应用
  7. W-Cms XSS和遍历目录漏洞
  8. 清理电脑文件夹中的Thumbs.db文件
  9. [云盘]共享文件列表
  10. 面试精选-solr篇
  11. 万物皆可GAN之pytorch和神经网络
  12. 什么是好用的身份证实名认证api接口?其应用场景有哪些?
  13. 用友NC单据UI基本代码示例
  14. Hello hello ~
  15. 在栈中压入一个字符串c语言,一 道C语言试题的探讨
  16. About 不以物喜 不以己悲
  17. 关闭selinux的方法汇总
  18. 2021年技术自媒体经验分享 —— 开始尝试认真做 CSDN 的一年后的复盘
  19. RHCE之路--15更新 Ansible 库的密钥
  20. 在不交智商税的情况下,如何判断一场知乎live的质量?

热门文章

  1. MBA-day6数学-应用题-工程问题-习题
  2. U8销售出库单API接口 --参照发货通知单
  3. 阿里云AI训练营第五天
  4. 安装micro/go-micro
  5. ARM Linux中断机制分析
  6. 联想t450进入bios设置按哪个键_联想pad T450用U盘做系统,读取不到硬盘该如何处理,如何进BIOS设置,...
  7. CF407B 「Long Path」
  8. php.ini配置中文详解
  9. 常用的几款Vue移动端UI推荐
  10. J - 【黄色】这题真的是模板题 (Gym - 102072J )(spfa)