前言
今日在做项目的时分,遇到了需要打开文件管理中某个文件夹的需求,在网上看到一个大佬是这样写的:
private void openMusic(){
Uri uri = Uri.parse("content://com.android.externalstorage.documents/document/primary:Music");
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri);
startActivityForResult(intent, 1);
}
本想着学习过来直接运用,可是IDE上清晰的 startActivityForResult,让我觉得应该细心研究一下这个办法了。
startActivityForResult用法
在以前,咱们经常会遇到发动一个 Activity,并从中获取数据的需求,此外还有一些常见的场景是调用系统相机、调用相册获取相片、调用通讯录等。一般的做法就是运用 Intent 带着数据,之后将 Intent 和恳求码传入 startActivityForResult
办法来发动下一个Activity
startActivityForResult(intent,1)
终究在 onActivityResult
办法中来接纳回来的数据。完成 onActivityResult 办法
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1 && resultCode == Activity.RESULT_OK){
// 处理带回的数据
}
}
可是跟着运用的开发 onActivityResult 回调办法难以解耦复用,后期保护困难。于是Google推出Activity Results API
Activity Results API介绍
Activity Results API 是 Google官方推荐的Activity、Fragment获取数据的办法。它有两个首要的用途:
- 替代 startActivityForResult 办法,去发动Activity并回来成果
- 替代 requestPermissions 办法,去恳求运行时权限
registerForActivityResult()
在 AppCompatActivity 或者 Fragment 中运用 registerForActivityResult() 办法来代替 startActivityForResult() (Android api29中运用startActivityForResult提示已过时,应该变成registerForActivityResult)。该办法接纳两个参数并回来ActivityResultLauncher。其间两个参数一个是ActivityResultContract,一个是ActivityResultCallback。终究运用 activityResultLauncher 调用launch(...)
发动方针Activity。
-
ActivityResultLauncher
用于发动另一个 Activity -
ActivityResultContract
这是一个协议类,它的两个泛型别离表明发动参数的类型和回来成果的类型。能够经过继承的办法来自界说 ActivityResultContract -
ActivityResultCallback
是单一办法接口,内部只有 onActivityResult 这一个办法,能够接受ActivityResultContract 中界说的输出类型的对象
registerForActivityResult部分源码
ActivityResultCallback部分源码
惯例用法
下面完成一个最基本的小例子,首先我在 MainActivity 的 onCreate 办法中,进行如下完成
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == RESULT_OK) {
//获取回来的成果
String data = result.getData().getStringExtra("data");
Log.d(TAG, "onCreate: " + data);
Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
}
});
Button button1 = findViewById(R.id.button_2);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
activityResultLauncher.launch(intent);
}
});
}
之后我在 SecondActivity 的 onCreate 办法中,进行如下完成
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
Intent intent = new Intent();
intent.putExtra("data", "这是回调的数据");
setResult(RESULT_OK, intent);
finish();
}
需要注意的是:
registerForActivityResult只能在onCreate()中注册,否则在运用的时分会报反常
java.lang.IllegalStateException: LifecycleOwner com.yxf.extensions.MainActivity@f8e47f4 is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
本文正在参与「金石方案」