onActivityResult的现状
- 回调方法各种嵌套、耦合严重、难以维护
- 处理结果都耦合在onActivityResult回调中
- 定义许多额外的常量来处理返回结果
Activity Results API
- Activity Results API 是 Google官方推荐的Activity、Fragment获取返回结果的方式。
一、Activity Results API 中两个重要的组件:
ActivityResultContract和ActivityResultLauncher。
- ActivityResultContract: 协议,它定义了如何传递数据和如何处理返回的数据。ActivityResultContract是一个抽象类,你需要继承它来创建自己的协议,每个 ActivityResultContract 都需要定义输入和输出类,如果您不需要任何输入,可使用 Void作为输入类型。
- ActivityResultLauncher: 启动器,调用ActivityResultLauncher的launch方法来启动页面跳转,作用相当于原来的startActivity()
二、如何使用
- 首先再build.gradle中添加依赖
implementation 'androidx.activity:activity:1.2.0-beta01'
implementation 'androidx.fragment:fragment:1.3.0-beta01'
- 在Activity中新建内部类,继承ActivityResultContract
class ResultContract extends ActivityResultContract<String, String> {
@NonNull
@Override
public Intent createIntent(@NonNull Context context, String input) {
Intent intent = new Intent(ResultActivity.this, ResultBackOneActivity.class);
intent.putExtra("text_string", input);
return intent;
}
@Override
public String parseResult(int resultCode, @Nullable Intent intent) {
return intent.getStringExtra("one_back");
}
}
- 然后初始化ActivityResultLauncher,在回调方法中可以获取到带回来的值 result
ActivityResultLauncher launcher = registerForActivityResult(new ResultContract(), new ActivityResultCallback<String>() {
@Override
public void onActivityResult(String result) {
Toast.makeText(ResultActivity.this, result, Toast.LENGTH_SHORT).show();
}
});
- 然后在跳转方法中使用launcher进行页面见传值,使用.launcher()方法启动
tv_intent_one.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launcher.launch("这里是第一个跳转");
}
});
- 在目标页面中,处理还是一样的,返回数据时也是之前的操作
TextView tv_intent_one = findViewById(R.id.tv_intent_one);
tv_intent_one.setText(getIntent().getStringExtra("text_string"));
tv_intent_one.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setResult(RESULT_OK, new Intent().putExtra("one_back", "这里是第一个跳转的返回"));
finish();
}
});
三、使用预定的Contract
为了使用方便,Google预定义了许多类型
- 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返回,应用程序可以完全管理返回目录中的文档。
四、如何使用预定的Contract
- StartActivityForResult的使用,注意返回值定义为ActivityResult。在目标页面的处理同上
ActivityResultLauncher mylauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
Toast.makeText(ResultActivity.this, result.getData().getStringExtra("two_back")+"-----", Toast.LENGTH_SHORT).show();
}
});
// 跳转方法
Intent intent = new Intent(ResultActivity.this, ResultBackTwoActivity.class);
intent.putExtra("text_string","这里是第二个跳转");
mylauncher.launch(intent);
- 单个权限请求(RequestPermission)和多个权限请求(RequestMultiplePermissions)的使用
// 初始化单个权限请求
ActivityResultLauncher requestpermiss = registerForActivityResult(new ActivityResultContracts.RequestPermission(), new ActivityResultCallback<Boolean>() {
@Override
public void onActivityResult(Boolean result) {
Toast.makeText(ResultActivity.this, "获取权限"+result, Toast.LENGTH_SHORT).show();
}
});
// 初始化多个权限请求
ActivityResultLauncher requestpermissgroup = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
@Override
public void onActivityResult(Map<String, Boolean> result) {
Set entries = result.entrySet( );
if(entries != null) {
Iterator iterator = entries.iterator( );
while(iterator.hasNext( )) {
Map.Entry entry = (Map.Entry) iterator.next( );
Object key = entry.getKey( );
Object value = entry.getValue();
Toast.makeText(ResultActivity.this, key+"权限获取"+value, Toast.LENGTH_SHORT).show();
}
}
}
});
// 单个权限请求实现
requestpermiss.launch(Manifest.permission.BLUETOOTH);
// 多个权限请求实现
String[] permissgroup = new String[]{
Manifest.permission.BLUETOOTH,
Manifest.permission.NFC,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA};
requestpermissgroup.launch(permissgroup);