关于android:Android从其他Activity获取结果registerForActivityResult

6次阅读

共计 4924 个字符,预计需要花费 13 分钟才能阅读完成。

「Android」从其余 Activity 获取后果:registerForActivityResult()

简介

  • Activity Result APIs 能够取代 startActivityForResult 办法,去 启动 Activity 以获取后果
  • Activity Result APIs 能够取代 requestPermissions 办法,去 申请运行时权限

背景

启动一个 activity(无论是本利用中的 activity 还是其余利用中的 activity)不肯定是单向操作,也能够启动另一个 activity 并接管返回的后果。
常见的场景是调用零碎相机、调用相册获取照片、调用通讯录、获取局部非凡权限等,传统形式通常是通过 Intent 携带数据,而后应用 startActivityForResult 办法来启动下一个 Activity,而后通过 onActivityResult 来接管返回的数据。
传统形式的问题在于:

  • 在启动 activity 以获取后果时,可能会呈现过程和 activity 因内存不足而被销毁的状况
  • onActivityResult 回调办法嵌套耦合重大,逻辑凌乱导致难以保护

为启动 Activity 获取的后果注册后果回调

基于上述存在问题,Activity Result APIs 将启动 Activity 的后果回调,与启动 Activity 的逻辑进行了拆散。

位于 ComponentActivity 或 Fragment 中时,Activity Result API 提供了 registerForActivityResult() API,用于注册后果回调。
registerForActivityResult() 承受 ActivityResultContractActivityResultCallback 作为参数,并返回 ActivityResultLauncher,用来启动另一个 activity,其中:

  • ActivityResultContract 定义生成后果所需的输出类型以及后果的输入类型。这些 API 可为拍照和申请权限等根本 intent 操作提供默认协定,同时还能够创立自定义协定。
  • ActivityResultCallback 是繁多办法接口,带有 onActivityResult() 办法,可承受 ActivityResultContract 中定义的输入类型的对象:
ActivityResultLauncher<String> mGetContent = registerForActivityResult(new GetContent(),
    new ActivityResultCallback<Uri>() {
        @Override
        public void onActivityResult(Uri uri) {// Handle the returned Uri}
});

启动 Activity 以获取后果

registerForActivityResult() 仅为启动 Activity 获取的后果注册后果回调,但它自身不会并启动另一个 activity 并收回后果申请。启动 Activity 的操作由 registerForActivityResult() 返回的 ActivityResultLauncher 的实例对象负责。

如果存在输出参数,ActivityResultLauncher 的实例对象会依据输出参数去匹配 ActivityResultContract 的类型。调用 ActivityResultLauncher 的实例对象的 launch() 办法,会启动 Activity 并获取后果。当用户实现后续 activity 并返回时,零碎将执行 ActivityResultCallback 中的 onActivityResult() 办法。

ActivityResultLauncher<String> mGetContent = registerForActivityResult(new GetContent(),
    new ActivityResultCallback<Uri>() {
        @Override
        public void onActivityResult(Uri uri) {// Handle the returned Uri}
});

@Override
public void onCreate(@Nullable savedInstanceState: Bundle) {
    // ...

    Button selectButton = findViewById(R.id.select_button);

    selectButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            // Pass in the mime type you'd like to allow the user to select
            // as the input
            mGetContent.launch("image/*");
        }
    });
}

留神:因为在调用 launch() 与触发 onActivityResult() 回调的两个工夫点之间,过程和 activity 可能会被销毁,因而,处理结果所需的任何其余状态,都必须与这些 API 离开保留和复原。

预约义 Contract

在 Activity Result APIs 中提供了一系列预约义 Contract 供开发者去别离 启动 Activity 以获取后果 申请运行时权限

  • 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

    ActivityResultLauncher activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
        @Override
        public void onActivityResult(ActivityResult result) {}});

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
        activityResultLauncher.launch(intent);
    }

RequestMultiplePermissions

    ActivityResultLauncher activityResultLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
        @Override
        public void onActivityResult(Map<String, Boolean> result) {}});

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String[] permissions = {Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE};
        activityResultLauncher.launch(permissions);
    }

新旧比照:onActivityResult & Activity Result APIs

旧:

public void openSomeActivityForResult() {Intent intent = new Intent(this, SomeActivity.class);
    startActivityForResult(intent, 123);
}

@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {if (resultCode == Activity.RESULT_OK && requestCode == 123) {doSomeOperations();
    }
}

新:

// You can do the assignment inside onAttach or onCreate, i.e, before the activity is displayed
ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
        new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {if (result.getResultCode() == Activity.RESULT_OK) {
                    // There are no request codes
                    Intent data = result.getData();
                    doSomeOperations();}
            }
        });

public void openSomeActivityForResult() {Intent intent = new Intent(this, SomeActivity.class);
    someActivityResultLauncher.launch(intent);
}

参考

https://segmentfault.com/a/11…
https://developer.android.com…

正文完
 0