Goolgle推荐 onActivityResult的替代方式
1、Activity Results API
Activity Results API 是 Google官方推荐的Activity、Fragment获取返回结果的方式。
Activity Results API 到底怎么用?相比onActivityResult有哪些优势?接下来,将一一为你解答。
在介绍如何使用之前,先为大家介绍Activity Results API 中两个重要的组件:
ActivityResultContract和ActivityResultLauncher。
- ActivityResultContract: 协议,它定义了如何传递数据和如何处理返回的数据。ActivityResultContract是一个抽象类,你需要继承它来创建自己的协议,每个 ActivityResultContract 都需要定义输入和输出类,如果您不需要任何输入,可使用 Void
- ActivityResultLauncher: 启动器,调用ActivityResultLauncher的launch方法来启动页面跳转,作用相当于原来的startActivity()
2、使用 Activity Results API 获取Activity返回的结果
在app下的build.gragle中添加依赖
dependencies {
def activity_version = "1.2.2"
// Java language implementation
implementation "androidx.activity:activity:$activity_version"
// Kotlin
implementation "androidx.activity:activity-ktx:$activity_version"
}
自定义contract继承自ActivityResultContract<I,O>,其中,I是输入的类型,O是输出的类型。需要实现2个方法,createIntent和parseResult,输入类型I作为createIntent的参数,输出类型O作为parseResult方法的返回值
public class MyActivityResultContract extends ActivityResultContract<String,Integer>{
@NonNull
@Override
public Intent createIntent(@NonNull Context context, String input) {
//Intent 跳转到其它页面,可携带参数
return null;
}
@Override
public Integer parseResult(int resultCode, @Nullable Intent intent) {
//获取返回数据的result
return null;
}
}
注册MyActivityResultContract,registerForActivityResult方法,得到返回值ActivityResultLauncher的对象launcher,通过launcher跳转
3、为了方便使用,google给出预定义了很多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返回,应用程序可以完全管理返回目录中的文档。
通过registerForActivityResult进行注册,下面给出两个例子作为演示:一个是正常的数据回传,一个是运行时权限的申请
private ActivityResultLauncher<Intent> mLauncher;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
String stringExtra = result.getData().getStringExtra("result");
Toast.makeText(MainActivity.this, stringExtra, Toast.LENGTH_SHORT).show();
}
}
});
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
intent.putExtra("name","Tom");
mLauncher.launch(intent);
}
});
final String[] permission ={Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.READ_CONTACTS};
ActivityResultLauncher<String[]> permissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
@Override
public void onActivityResult(Map<String, Boolean> result) {
for (int i = 0; i < permission.length; i++) {
if(result.containsKey(permission[i])){
Toast.makeText(MainActivity.this, permission[i], Toast.LENGTH_SHORT).show();
}
}
}
});
permissionLauncher.launch(permission);
}
4、小结
新的Activity Result API提供了一种执行许多常见任务的简便方法,比如我们调用第三方APP 获取数据,请求权限、拍照、选图片、获取联系人等等。除此之外,降低了代码的耦合,减少了样板代码(比如,定义requestCode常量)。
另外,startActivityForResult和onActivityResult已经被废弃,官方也是强烈建议使用这种方式来进行数据传递并获取Activity返回的数据。