Activity Result Api使用

谷歌官方已经将startActivityForResult()标记为过时,并强烈推荐使用Activity Result API作为Androidx中activity和fragment获取返回值的方式,本文主要记录其用法。

1.引入库 

     implementation 'androidx.appcompat:appcompat:1.3.1' 

2.API简介

在ComponentActivity和Fragment中,Activity Result API提供registerForActivityResult()方法

 参数1:ActivityContract<I, O>类型

用于定义启动时输入的类型和结果的输出类型,具体有以下这些Contract:

StartActivityForResult:通用的Contract,不做任何转换,Intent作为输入,ActivityResult作为输出

RequestPermission:用于请求单个权限,输入为权限值,例如:

android.Manifest.Permission.CALL_PHONE,输出为布尔值,表示权限申请是否成功

TakePicturePreview:调用M e di a S to re.ACTION_IMAGE_CAPTURE拍照,返回值为Bitmap

TakePicture:调用MediaStore.ACTION_VIDEO_CAPTURE拍照,并将图片保存到给定的Uri地址,返回true表示保存成功

TakeVideo:调用MediaStore.ACTION_VIDEO_CAPTURE拍摄视频,保存到给定的Uri地址,但会一张缩略图

PickContact:从通讯录App获取联系人

GetContent:提示选择一条内容,返回一个通过COntentResolver#openInputStream(Uri)访问原生数据的Uri地址(content://形式)默认情况下,它增加了

Intent#CATEGORY_OPENABLE,返回可以表示流的内容

CreateDocument:提示用户选择一个文档,返回一个(file: or http: or content:)开头的Uri

OpenMultipleDocuments: 提示用户选择文档(可以选择多个),分别返回它们的Uri,以List的形式。

OpenDocumentTree: 提示用户选择一个目录,并返回用户选择的作为一个Uri返回,应用程序可以完全管理返回目录中的文档。

参数2:ActivityResultCallback<O>,这是一个单一方法接口(SMA),带有onActivityResult(),可以接受ActivityContract中定义的输出类型的对象

返回值:ActivityResultLauncher,用于启动activity

如果有多个Contract或者单独回调的activity结果调用,可以多次调用registerForActivityResult()创建多个ActivityResultLauncher

3.示例

示例1:activity跳转和申请单个权限

    private lateinit var mBtn: Button
    private lateinit var dailBtn: Button
    //跳转activity并请求结果
    private val mMainActivityLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val data = result.data?.getStringExtra("result")
            Toast.makeText(this, "Result from SecondActivity is $data", Toast.LENGTH_SHORT).show()
        }
    }
    //申请单个权限
    private val mPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
        if (isGranted) {
            call()
        } else {
            Toast.makeText(this, "you denied the permission request!", Toast.LENGTH_SHORT).show()
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mBtn = findViewById<Button>(R.id.btn).apply {
            setOnClickListener {
                val intent = Intent(this@MainActivity, SecondActivity::class.java)
                mMainActivityLauncher.launch(intent)
            }
        }
        dailBtn = findViewById<Button>(R.id.dailBtn).apply {
            setOnClickListener {
                if (ContextCompat.checkSelfPermission(this@MainActivity, android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    mPermissionLauncher.launch(android.Manifest.permission.CALL_PHONE)
                } else {
                    call()
                }
            }
        }
    }
    private fun call() {
        val intent = Intent(Intent.ACTION_CALL)
        intent.data = Uri.parse("tel:10000")
        startActivity(intent)
    }

示例2:google官方示例,输入一个字符串,返回一个Uri

val getContent = registerForActivityResult(GetContent()) { uri: Uri? ->
    // Handle the returned Uri
}

override fun onCreate(savedInstanceState: Bundle?) {
    // ...

    val selectButton = findViewById<Button>(R.id.select_button)

    selectButton.setOnClickListener {
        // Pass in the mime type you'd like to allow the user to select
        // as the input
        getContent.launch("image/*")
    }
}

4.在单独的类中接受activity的结果

ComponentActivity和Fragment类通过使用ActivityResultCaller接口来允许使用registerForActivityResult() API。但是可以通过直接使用ActivityResultRegistry在为实现ActivityResultCaller的单独类中接收结果。

例如,实现一个LifecycleObserver,用于处理Contract的注册和启动器的启动:

Google官方示例:

class MyLifecycleObserver(private val registry : ActivityResultRegistry)
        : DefaultLifecycleObserver {
    lateinit var getContent : ActivityResultLauncher<String>

    override fun onCreate(owner: LifecycleOwner) {
        getContent = registry.register("key", owner, GetContent()) { uri ->
            // Handle the returned Uri
        }
    }

    fun selectImage() {
        getContent.launch("image/*")
    }
}

class MyFragment : Fragment() {
    lateinit var observer : MyLifecycleObserver

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...

        observer = MyLifecycleObserver(requireActivity().activityResultRegistry)
        lifecycle.addObserver(observer)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val selectButton = view.findViewById<Button>(R.id.select_button)

        selectButton.setOnClickListener {
            // Open the activity to select an image
            observer.selectImage()
        }
    }
}

 5.创建自定义Contract:待补充

参考:获取 activity 的结果  |  Android 开发者  |  Android Developers

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值