使用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()
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM