优雅Intent ActivityResult
ActivityResult 新时代
跳转 Activity 获取返回值,我们怎么做?
AndroidX Activity 1.2.0-alpha02 和 Fragment 1.3.0-alpha02 是新旧时代的划分线。
调用方假设为 IntentsActivity,被调用方假设为 IntentResultActivity。
旧石器时代:
调用方:
- 调用 startActivityForResult 传入请求码,传输数据(可选)。
- 覆写 onActivityResult 方法,根据请求码和结果码获取返回结果信息。
1
2
3
4
5
6
7
8class IntentsConstants {
companion object {
const val REQUEST_CODE_OLD = 1
const val RESULT_CODE_OLD = 100
const val EXTRA_RESULT_OLD_REQUEST = "extra_result_old_request"
const val EXTRA_RESULT_OLD_RESULT = "extra_result_old_result"
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18fun start() {
val intent = Intent(this@IntentsActivity, IntentResultActivity::class.java)
val bundle = Bundle()
bundle.putString(EXTRA_RESULT_OLD_REQUEST, "OLD")
intent.putExtras(bundle)
startActivityForResult(
intent,
IntentsConstants.REQUEST_CODE_OLD
)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == IntentsConstants.REQUEST_CODE_OLD && resultCode == IntentsConstants.RESULT_CODE_OLD) {
val result = data?.extras?.getString(IntentsConstants.EXTRA_RESULT_OLD_RESULT)
Toast.makeText(this@IntentsActivity, "result: $result", Toast.LENGTH_SHORT).show()
}
}被调用方:
- finish 前 调用 setResult,传入结果码,返回数据(可选)。
1
2
3
4
5
6
7
8
9override fun onBackPressed() {
val resultIntent = Intent()
val resultBundle = Bundle()
resultBundle.putString(IntentsConstants.EXTRA_RESULT_OLD_RESULT, "resultold")
resultIntent.putExtras(resultBundle)
setResult(IntentsConstants.RESULT_CODE_OLD, resultIntent)
super.onBackPressed()
}新石器时代
- 引入依赖 AndroidX Activity 1.2.0-alpha02 和 Fragment 1.3.0-alpha02 或以上版本。
- 定义协议
1
2implementation 'androidxactivity:activity-ktx:1.2.0-beta02'
implementation 'androidxfragment:fragment-ktx:1.3.0-beta02'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22class IntentResultContract : ActivityResultContract<String, String>() {
override fun createIntent(context: Context, input: String?): Intent {
return Intent(context, IntentResultActivity::class.java).apply {
putExtras(Bundle().apply {
putString(EXTRA_RESULT_NEW_REQUEST, "NEW")
})
}
}
override fun parseResult(resultCode: Int, intent: Intent?): String? {
val data = intent?.extras?.getString(EXTRA_RESULT_NEW_RESULT)
return if (resultCode == RESULT_CODE_NEW && data != null) data
else null
}
companion object {
const val RESULT_CODE_NEW = 200
const val EXTRA_RESULT_NEW_REQUEST = "extra_result_new_request"
const val EXTRA_RESULT_NEW_RESULT = "extra_result_new_result"
}
}调用方:
- 注册协议
- 启动协议
1
2
3
4
5
6
7
8private val intentsActivityLauncher =
registerForActivityResult(IntentResultContract()) { result ->
Toast.makeText(this@IntentsActivity, "result: $result", Toast.LENGTH_SHORT).show()
}
fun start() {
intentsActivityLauncher.launch("NEW")
}被调用方:
- finish 前 调用 setResult,传入结果码,返回数据(可选)。
1
2
3
4
5
6
7
8
9override fun onBackPressed() {
val resultIntent = Intent()
val resultBundle = Bundle()
resultBundle.putString(IntentsConstants.EXTRA_RESULT_NEW_RESULT, "resultnew")
resultIntent.putExtras(resultBundle)
setResult(IntentsConstants.RESULT_CODE_NEW, resultIntent)
super.onBackPressed()
}
基础概念
- ActivityResultContract:协议,定义了如何传递数据和如何处理返回的数据。
- ActivityResultLauncher: 启动器,调用 ActivityResultLauncher 的 launch 方法来启动页面跳转,作用相当于原来的 startActivity()。
库中默认已实现 Contract
库中默认已实现的 Contract 都定义在 androidx.activity.result.contract.ActivityResultContracts 中。
StartActivityForResult: 通用的 Contract,不做任何转换,Intent 作为输入,ActivityResult 作为输出,这也是最常用的一个协定。
RequestMultiplePermissions: 用于请求一组权限。
RequestPermission: 用于请求单个权限。
TakePicturePreview: 调用 MediaStore.ACTION_IMAGE_CAPTURE 拍照,返回值为 Bitmap 图片。
TakePicture: 调用 MediaStore.ACTION_IMAGE_CAPTURE 拍照,并将图片保存到给定的 Uri 地址,返回 true 表示保存成功。
TakeVideo: 调用 MediaStore.ACTION_VIDEO_CAPTURE 拍摄视频,保存到给定的 Uri 地址,返回一张缩略图。
PickContact: 从通讯录 APP 获取联系人。
GetContent: 提示用选择一条内容,返回一个通过 ContentResolver#openInputStream(Uri) 访问原生数据的 Uri 地址(content://形式) 。默认情况下,它增加了 Intent#CATEGORY_OPENABLE, 返回可以表示流的内容。
CreateDocument: 提示用户选择一个文档,返回一个(file:/http:/content:)开头的 Uri。
OpenMultipleDocuments: 提示用户选择文档(可以选择多个),分别返回它们的 Uri,以 List 的形式。
OpenDocumentTree: 提示用户选择一个目录,并返回用户选择的作为一个 Uri 返回,应用程序可以完全管理返回目录中的文档。
ActivityResult 新时代优势
以回调的方式获取返回值,而不是覆写方法。个人认为覆写方法获取返回值有一种“割裂”的感觉。
减少了样板代码,自定义 Contract 可以复用传值和解析值的逻辑。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!