Android 带回调的启动Activity 推荐使用registerForActivityResult
中registerForActivityResult的 api找不到?
registerForActivityResult这个api是在 implementation ‘androidx.appcompat:appcompat:1.3.1’
这个依赖里面 的, 且必须在 1.3.1版本之后(包含1.3.1)才有.
ActivityResultLauncher<PickVisualMediaRequest> pickMedia = registerForActivityResult(new ActivityResultContracts.PickVisualMedia(), uri -> {
// Callback is invoked after the user selects a media item or closes the
});
pickMedia.launch(new PickVisualMediaRequest.Builder().setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE).build());
或者
//常规带回调启动Activity
val launcher = registerForActivityResult(object : ActivityResultContract<String, String>() {
override fun createIntent(context: Context, input: String?): Intent {
//创建启动页面所需的Intent对象,传入需要传递的参数
return Intent(this@MainActivity, SecondActivity::class.java).apply {
putExtra("key", input)
}
}
override fun parseResult(resultCode: Int, intent: Intent?): String {
//页面回传的数据解析,相当于原onActivityResult方法
val data = intent?.getStringExtra("result") ?: ""
return if (resultCode == RESULT_OK) data else ""
}
}) {
//获取parseResult解析的数据
Log.e(TAG, "data:$it")
}
launcher.launch(“传递给第二个页面的数据:你好吗?”)
ActivityResultContract:内部有两个抽象方法,一个createItent,创建需要启动的页面Intent对象,同时也可传参;另外的parseResult,数据的解析在这里处理,并返回。
ActivityResultCallBack:内部只有一个抽象方法onActivityResult(),上面的写法使用的lambda简化写法,直接移到方法括号外部,这里面的回调方法是接收上面parseResult解析的数据。
注意:registerForActivity返回一个launcher对象,创建的时候得在Activity中的onCreate方法中创建,使用的时候这样用。
从上面可知,我们主要在创建contract的时候比较麻烦,不过官方给了如下实现类,包含了开发中常见业务:比如选择图片、视频、联系人、权限申请等。
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返回,应用程序可以完全管理返回目录中的文档。
1、startActivityForResult
val register = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if(it.resultCode == RESULT_OK){
val keyWords = it.data?.getStringExtra(SearchCompanyActivity.KEY_CODE) ?: “”
if (keyWords.isNotEmpty()) {
mViewModel.keyWords = keyWords
mVb.tvSearch.text = mViewModel.keyWords
mVb.ivCleanKeywords.visibility = View.VISIBLE
mVb.refreshLayout.autoRefresh()
}
}
}
//启动Activity
register.launch(Intent(this@AdvanceOnWorkActivity,SearchCompanyActivity::class.java))
2、单个权限申请
//单个权限申请
val launcherPermission = registerForActivityResult(ActivityResultContracts.RequestPermission()){
if(it) {
//同意
}else{
//拒绝
}
}
launcherPermission.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
3、多个权限申请
//多个权限申请单个权限
val launcherPermissions = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()){
//逐个判断权限是否有
if(it[Manifest.permission.CAMERA]!!){
//同意
}else{
//拒绝
}
if(it[Manifest.permission.WRITE_EXTERNAL_STORAGE]!!){
//同意
}else{
//拒绝
}
}
launcherPermissions.launch(arrayOf(Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE))
4、图片选择(单张、多张)
//选择一张图片
val launcherImg = registerForActivityResult( ActivityResultContracts.OpenDocument()){
Log.e(TAG,“path:${it.path}”)
}
launcherImg.launch(arrayOf(“image/*”))
//选择多张图片
val launcherImgs = registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()){
it.forEach { uri->
Log.e(TAG,uri.toString())
}
}