再见!onActivityResult!你好,2024必看

但也有一些问题…

随着应用的扩展,onActivityResult回调方法各种嵌套、耦合严重、难以维护。 最常见的场景就是调用系统相机相册获取照片了。代码可能像是如下这样:

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQUEST_PERMISSION -> {
// 处理权限
}
REQUEST_CAMERA -> {
// 相机获取图片结果
}
REQUEST_ALBUM -> {
// 相册获取图片结果
}
REQUEST_CROP -> {
// 系统裁剪
}
}
}

super.onActivityResult(requestCode, resultCode, data)
}

companion object {
const val REQUEST_PERMISSION = 1001
const val REQUEST_CAMERA = 1002
const val REQUEST_ALBUM = 1003
const val REQUEST_CROP = 1004
}
}

各种处理结果都耦合在onActivityResult回调里,并且还得定义一堆额外的常量REQUEST_CODE,用与判断是哪个请求的回调结果。

onActivityResult 现状?

Google 可能也意识到onActivityResult的这些问题,在androidx.activity:activity:1.2.0-alpha02androidx.fragment:fragment:1.3.0-alpha02 中,已经废弃了startActivityForResultonActivityResult方法。

/**

  • {@inheritDoc}
  • @deprecated use
  • {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
  • passing in a {@link StartActivityForResult} object for the {@link ActivityResultContract}.
    */
    @Override
    @Deprecated
    public void startActivityForResult(@SuppressLint(“UnknownNullness”) Intent intent,
    int requestCode) {
    super.startActivityForResult(intent, requestCode);
    }

/**

  • {@inheritDoc}
  • @deprecated use
  • {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
  • with the appropriate {@link ActivityResultContract} and handling the result in the
  • {@link ActivityResultCallback#onActivityResult(Object) callback}.
    */
    @CallSuper
    @Override
    @Deprecated
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) {
    super.onActivityResult(requestCode, resultCode, data);
    }
    }

可以看到,这两个方法都被标记为了Deprecated,那这两个方法不推荐使用了,Google推荐使用什么方式从Activity中更好的获取数据呢?答案就是 Activity Results API

Activity Results API

Activity Results API 是 Google官方推荐的Activity、Fragment获取数据的方式。

Activity Results API 到底怎么用?相比onActivityResult有哪些优势?接下来,将一一为你解答。

在介绍如何使用之前,先为大家介绍Activity Results API 中两个重要的组件:ActivityResultContractActivityResultLauncher

  • ActivityResultContract: 协议,它定义了如何传递数据和如何处理返回的数据。ActivityResultContract是一个抽象类,你需要继承它来创建自己的协议,每个 ActivityResultContract 都需要定义输入和输出类,如果您不需要任何输入,可使用 Void(在 Kotlin 中,使用 Void? 或 Unit)作为输入类型。

  • ActivityResultLauncher: 启动器,调用ActivityResultLauncherlaunch方法来启动页面跳转,作用相当于原来的startActivity()

使用 Activity Results API 在Activity之间传递数据
1. 首先,在app下的build.gradle中加入依赖:

implementation ‘androidx.activity:activity:1.2.0-beta01’
implementation ‘androidx.fragment:fragment:1.3.0-beta01’

2. 定义协议

新建一个Contract类,继承自ActivityResultContract<I,O>,其中,I是输入的类型,O是输出的类型。需要实现2个方法,createIntentparseResult,输入类型I作为createIntent的参数,输出类型O作为parseResult方法的返回值,在下面的例子中,输入输出类型都是String:

class MyActivityResultContract: ActivityResultContract<String,String>(){
override fun createIntent(context: Context, input: String?): Intent {
return Intent(context,SecondActivity::class.java).apply {
putExtra(“name”,input)
}
}

override fun parseResult(resultCode: Int, intent: Intent?): String? {
val data = intent?.getStringExtra(“result”)
return if (resultCode == Activity.RESULT_OK && data != null) data
else null
}

}

如上代码,我们在createIntent方法中创建了Intent,并且携带了参数name,在parseResult方法中,获取了返回的数据result

3. 注册协议,获取启动器-ActivityResultLauncher

注册协议,使用registerForActivityResult方法,该方法由ComponentActivity或者Fragment提供,接受2个参数,第一个参数就是我们定义的Contract协议,第二个参数是一个回调ActivityResultCallback<O>,其中O就是前面Contract的输出类型。代码如下:

private val myActivityLauncher = registerForActivityResult(MyActivityResultContract()){result ->
Toast.makeText(applicationContext,result,Toast.LENGTH_SHORT).show()
textView.text = “回传数据:$result”
}

如上代码,注册了MyActivityResultContract,registerForActivityResult方法的返回值是ActivityResultLauncher, 因此我们定义了一个myActivityLauncher,回调方法中,result就是从上一个界面传回的值。这里我们简单的用Toast显示。

4. 最后,调用启动器的launch方法开启界面跳转

MainActivity中添加一个Button,点击Button时,调用launch方法跳转:

button.setOnClickListener {
// 开启页面跳转
myActivityLauncher.launch(“Hello,技术最TOP”)
}

SecondActivity的代码很简单:

class SecondActivity : AppCompatActivity(){

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.second_layout)

val name = intent.getStringExtra(“name”)
textView3.text = “接收到的数据为:$name”

button2.setOnClickListener {
val intent = Intent().apply {
putExtra(“result”,“Hello,依然范特西稀,我是回传的数据!”)
}
setResult(Activity.RESULT_OK,intent)
finish()
}
}
}

以上3步,就实现了使用新的Activity Results API 来完成Activity之间的数据传递,并获取Activity返回的数据

看一下效果:

这就完了吗?

你可能会有疑问,虽然确实减少了代码耦合,但是使用并不简单啊。

确实,但这并没有完!!!

预定义的Contract

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

文末

面试:如果不准备充分的面试,完全是浪费时间,更是对自己的不负责!

不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊

204888 (备注Android)**
[外链图片转存中…(img-g07kjFyo-1711827401338)]

文末

面试:如果不准备充分的面试,完全是浪费时间,更是对自己的不负责!

不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值