【Android】startActivityForResult优化方案
作者AS版本:Android Studio 2021.2.1稳定版:代号“花栗鼠”
实验时间:2022/08/07
一,背景
在郭霖老师的《第一行代码》3.3.5小结中,演示使用 Intent 向上返回数据的时候使用的是 startActivityForResult
,但是当你使用的时候却提示说:
来到官网一看:
好家伙,这 Google 的 Android 技术迭代也太快了吧,《第一行代码》第三版是用 Kotlin 写的,这出来才多久就好多地方被”迭代“了,哈哈哈哈。好吧,那我们就一起来探究探究这个 ActivityResult API
。
二,总体介绍
Activity Result API
会提供 registerForActivityResult()API
,用于注册结果回调。registerForActivityResult()
接受 ActivityResultContract
和 ActivityResultCallback
作为参数,并返回 ActivityResultLauncher
,供您用来启动另一个 activity。
ActivityResultContract
定义ActivityResultLauncher.launch
调用时需要传入的参数类型以及回调ActivityResultCallback
返回类型。这些 API 可为拍照和请求权限等基本 intent 操作提供默认协定,当然我们也可以自己重写。
ActivityResultCallback
是单一方法接口,只有 onActivityResult()
一个抽象方法(所以这里可以用 Lambda表达式),可接受 ActivityResultContract
中定义的输出类型的对象:
1 | //参数 ActivityResultContract ActivityResultCallback |
如果您有多个使用不同协定或需要单独回调的 activity 结果调用,则可以多次调用 registerForActivityResult()
,以注册多个 ActivityResultLauncher
实例。
!!!注意!!!:您必须在创建 fragment 或 activity 之前调用
registerForActivityResult()
;在 fragment 或 activity 的Lifecycle
达到CREATED
之前,您将无法启动ActivityResultLauncher
。这条注意非常重要!给我细品!!!也就是说
registerForActivityResult()
必须写在onCreate
方法外面,这是一个容易犯错的坑。
三,代码演示
registerForActivityResult()
只是注册了回调,它并不会自动给你启动另一个 activity 并发出结果请求。这些操作由返回的 ActivityResultLauncher
实例负责。
调用 launch()
会启动生成结果的过程。当用户完成后续 activity 并返回时,系统将执行 ActivityResultCallback
中的 onActivityResult()
。我们常见的做法就是直接在registerForActivityResult()
的后边直接用 Lambda 实现,具体一会看演示。
-
FirstActivity 中:
如果还用
startActivityForResult
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.first_layout)
button03.setOnClickListener {
startActivityForResult(Intent(this, SecondActivity::class.java), 1)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
1 -> if (resultCode == RESULT_OK) {
val returnedData = data?.getStringExtra("data_return")
Log.d("FirstActivity", "returned data is $returnedData")
}
}
}
}实现同样效果的
registerForActivityResult
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class MainActivity : AppCompatActivity() {
val activityResultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()
) { result ->
if ( result.resultCode == RESULT_OK) {
val returnData = result.data?.getStringExtra("data_return")
Log.d( "FirstActivity", "returned data is $returnData" )
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.first_layout)
button03.setOnClickListener {
activityResultLauncher.launch(Intent(this, SecondActivity::class.java))
}
}
} -
SecondActivity 中
onCreate
中 :1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//点这个按钮给 Activity1 传递数据
button2_2.setOnClickListener {
val intent = Intent()
intent.putExtra("data_return", "Hello FirstActivity")
setResult(RESULT_OK, intent)
finish()
/**
* 可以看到,我们还是构建了一个Intent,只不过这个Intent仅仅用于传递数据而已,它没有指定任何的“意图”。紧接着把要传递的数据存放在Intent中,然后调用了setResult()方法。这个方法非常重要,专门用于向上一个Activity返回数据。setResult()方法接收两个参数:第一个参数用于向上一个Activity返回处理结果,一般只使用RESULT_OK或RESULT_CANCELED这两个值;第二个参数则把带有数据的Intent传递回去。最后调用了finish()方法来销毁当前Activity
*/
}
//设置通过 Back 键也会返回数据
override fun onBackPressed() {
val intent = Intent()
intent.putExtra("data_return", "Hello FirstActivity")
setResult(RESULT_OK, intent)
finish()
}
参考资料: