使用registerForActivityResult替换onActivityResult

  • ~3.74K 字

近期在构建新项目的时候,发现onActivityResult方法已经被废弃了,于是有了尝试registerForActivityResult的想法。

标准使用

三个类ActivityResultLauncherActivityResultContractActivityResultCallback
首先ActivityResultLauncher作为主角,它需要配置一个泛型,这个泛型跟我们ActivityResultContract的返回值相同,ActivityResultLauncher通过launch方法来启动相应的界面或者功能。

  1. ActivityResultContract
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static class GalleryContract extends ActivityResultContract<Void, Uri> {

@NonNull
@Override
public Intent createIntent(@NonNull Context context, Void input) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
intent.setType("image/*");
return intent;
}

@Override
public Uri parseResult(int resultCode, @Nullable Intent intent) {
return intent.getData();
}
}

可以看到ActivityResultContract需要传入两个泛型,一个泛型作为createIntent方法的第二参数类型,这里可以作为我们intent传值的参数载体,ActivityResultContract的另一个泛型作为parseResult方法的返回值类型,我们可以自行定义从intent返回的参数类型。

  1. ActivityResultLauncher
1
2
3
4
5
6
private ActivityResultLauncher<Void> galleryLauncher = registerForActivityResult(new GalleryContract(), new ActivityResultCallback<Uri>() {
@Override
public void onActivityResult(Uri result) {
//todo something
}
});

把contract和ActivityResultCallback作为launcher的参数构建出launcher

  1. ActivityResultCallback
    这个里面就和onActivityResult方法回调一样的,只不过提供的结果参数是我们在contract中定义的。

4.启动launch
通过 galleryLauncher.launch(null);启动即可。

简单使用

ActivityResultContracts
这个类中提供了许多通用的方法

ActivityResultContracts.* 说明 参数 回调
StartActivityForResult 可以理解为startActivityForResult Intent ActivityResult(code,data)
TakePicture 通过MediaStore.ACTION_IMAGE_CAPTURE拍照并保存 保存文件的Uri 是否保存成功
TakePicturePreview 通过MediaStore.ACTION_IMAGE_CAPTURE拍照,但是只会拍一张小照片,作为thumbnail使用比较合适 null(Void) 图片的Bitmap
CaptureVideo 通过MediaStore.ACTION_VIDEO_CAPTURE拍摄视频并保存(androidx.activity 1.3.0-alpha08后提供,androidx.appcompat好像还没提供该类) 保存文件的Uri 是否保存成功。
RequestPermission 请求单个权限 Manifest.permission.* 用户是否授予该权限
RequestMultiplePermissions 请求多个权限 Array 回调为map, key为请求的权限,value为用户是否授予该权限
CreateDocument 通过Intent.ACTION_CREATE_DOCUMENT创建一个文件 默认文件名 选择目录后返回该文件的Uri
GetContent 通过Intent.ACTION_GET_CONTENT获取一个文件(这个方法可以通过android.content.ContentResolver.openInputStream获取到文件的原始数据) MIME类型 文件Uri
GetMultipleContents 通过Intent.ACTION_GET_CONTENT及Intent.EXTRA_ALLOW_MULTIPLE获取一个或多个文件(这个方法可以通过android.content.ContentResolver.openInputStream获取到文件的原始数据) MIME类型 文件List
OpenDocument 通过Intent.ACTION_OPEN_DOCUMENT选择文件 MIME类型 文件Uri
OpenDocumentTree 通过Intent.ACTION_OPEN_DOCUMENT_TREE选择一个目录,返回一个Uri并得到该目录下全部文档的管理权 目录初始位置Uri 选择目录Uri
OpenMultipleDocuments 通过Intent.ACTION_OPEN_DOCUMENT及Intent.EXTRA_ALLOW_MULTIPLE获取一个或多个文件 MIME类型 文件List
PickContact 通过Intent.ACTION_PICK从系统通讯录中获取联系人 null(Void) 联系人Uri
StartIntentSenderForResult* 构建IntentSender或PendingIntent 使用IntentSenderRequest.Builder构建 ActivityResult(code,data)
TakeVideo 通过MediaStore.ACTION_VIDEO_CAPTURE拍摄视频并保存(弃用了,官方解释是缩略图的Bitmap的返回不稳定,替换为上面的CaptureVideo即可) 保存文件的Uri 视频缩略图Bitmap

类似的使用如下

1
2
3
4
5
6
private ActivityResultLauncher<String> fileLauncher = registerForActivityResult(new ActivityResultContracts.GetContent(), new ActivityResultCallback<Uri>() {
@Override
public void onActivityResult(Uri result) {

}
});
1
2
3
4
5
6
private ActivityResultLauncher<Uri> videoLauncher = registerForActivityResult(new ActivityResultContracts.CaptureVideo(), new ActivityResultCallback<Boolean>() {
@Override
public void onActivityResult(Boolean result) {

}
});

注意

不能在需要使用的时候再去构建我们需要的launcher,否则会抛出异常
Activity

Fragment

赞助喵
非常感谢您的喜欢!
赞助喵
分享这一刻
让朋友们也来瞅瞅!