使用registerForActivityResult接受从activity返回的数据

不要再用onActivityResult了,用更高级更方便的。

启动一个activity需要一个laucher,这个laucher由registerForActivityResult返回,这个方法需要两个参数,一个参数为一个抽象类——ActivityResultContract<I, O>的实现,另一个参数是一个函数式接口的实现(用一个lambda表达式来代替)。

第一个参数要实现两个方法:

public abstract class ActivityResultContract<I, O> {

    /** Create an intent that can be used for {@link Activity#startActivityForResult} */
    public abstract @NonNull Intent createIntent(@NonNull Context context,
            @SuppressLint("UnknownNullness") I input);

    /** Convert result obtained from {@link Activity#onActivityResult} to O */
    @SuppressLint("UnknownNullness")
    public abstract O parseResult(int resultCode, @Nullable Intent intent);

第一个方法是配置结合input配置intent, 第二个方法是从intent取出数据返回。

第二个参数是对从intent取出的数据的处理。

技巧:官方为我们提供了很多便捷的实现好的第一个参数

预定义的Contract
大伙都看出来,新的Activity Results API使用起来好像有点麻烦,每次都得定义Contract。Google肯定考虑到了这个问题的,于是,Google 预定义了很多Contract,
把你们能想到的使用场景基本上都想到了,它们都定义在类ActivityResultContracts中,有以下这些Contract: StartActivityForResult() RequestMultiplePermissions() RequestPermission() TakePicturePreview() TakePicture() TakeVideo() PickContact() CreateDocument() OpenDocumentTree() OpenMultipleDocuments() OpenDocument() GetMultipleContents() GetContent()
下面分别介绍一下这些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返回,应用程序可以完全管理返回目录中的文档。

具体可参考:https://developer.android.com/reference/androidx/activity/result/contract/ActivityResultContracts

比如说,打开联系人列表选择一个联系人的ActivityResultContracts的实现为:

    /**
     * An {@link ActivityResultContract} to request the user to pick a contact from the contacts
     * app.
     * <p>
     * The result is a {@code content:} {@link Uri}.
     *
     * @see ContactsContract
     */
    public static final class PickContact extends ActivityResultContract<Void, Uri> {

        @NonNull
        @Override
        public Intent createIntent(@NonNull Context context, @Nullable Void input) {
            return new Intent(Intent.ACTION_PICK).setType(ContactsContract.Contacts.CONTENT_TYPE);
        }

        @Nullable
        @Override
        public Uri parseResult(int resultCode, @Nullable Intent intent) {
            if (intent == null || resultCode != Activity.RESULT_OK) return null;
            return intent.getData();
        }
    }

 

 

附上一个实例:

private val aLauncher =
        registerForActivityResult(ActivityResultContracts.PickContact()) { uri: Uri? ->
            // Handle the returned Uri
            //crimesuspect启动activity的注册laucher
            val queryFields = arrayOf(ContactsContract.Contacts.DISPLAY_NAME)
            val cursor =
                uri?.let {
                    requireActivity().contentResolver.query(
                        it,
                        queryFields,
                        null,
                        null,
                        null
                    )
                }
            cursor?.use {
                if (it.count > 0) {
                    it.moveToFirst()
                    val suspect = it.getString(0)
                    crime.suspect = suspect
                    crimeDetailViewModel.saveCrime(crime)
                    binding.crimeSuspect.text = suspect
                }
            }
        }


设置监听器的时候:binding.crimeSuspect.setOnClickListener {
aLauncher.launch()
}

 

posted @ 2021-06-02 14:03  ou尼酱~~~  阅读(4022)  评论(0编辑  收藏  举报