registerForActivityResult 解决 startActivityForResult(Intent!, Int): Unit is deprecated. Deprecated in Java

文章目录

    举两个例子

    例子一:开启蓝牙

    废弃的 startActivityForResult 写法:

    const val ENABLE_BLUETOOTH_REQUEST_CODE = 1
    
    val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
    startActivityForResult(enableBtIntent, ENABLE_BLUETOOTH_REQUEST_CODE)
    

    新的 registerForActivityResult 写法:

    val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
    requestBluetooth.launch(enableBtIntent)
    
    private var requestBluetooth =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == RESULT_OK) {
                    // granted
                } else {
                    // deny
                }
            }
    

    例子二: 拍照

    废弃的 startActivityForResult 写法:

    private fun dispatchTakePictureIntent() {
        val requestImageCapture = 1
        val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        try {
            startActivityForResult(takePictureIntent, requestImageCapture)
        } catch (e: ActivityNotFoundException) {
            // display error state to the user
        }
    }
    

    新的 registerForActivityResult 写法:

    val launcher =
    		registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    				if (result.resultCode == Activity.RESULT_OK) {
    						handleCameraImage(result.data)
    				}
    		}
    
    val btnTakePicture = findViewById<Button>(R.id.btnTakePicture)
    btnTakePicture.setOnClickListener {
    		// intent to open camera app
    		val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    		launcher.launch(cameraIntent)
    }
    

    registerForActivityResult 的用法

    主要分两步:

    1. registerForActivityResult: 注册回调逻辑。例如,操作成功/失败的处理;申请权限成功/失败的处理。
    2. launch intent: 执行。所以,示例二中将 registerForActivityResult 的返回命名为 launcher 非常简洁。

    代码可读性

    由于 registerForActivityResult 代码块相对较长,所以还是封装成一个函数毕竟好,可以有效提高可读性。

    但是,需要注意的是:

    private fun enableBluetooth() {
        val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        val launcher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == RESULT_OK) {
                    // granted
                } else {
                    // deny
                }
            }
        launcher.launch(intent)
    }
    

    这种方式会报错:

    ItemDetailHostActivity@79ab230 is attempting to register while current state is STARTED. LifecycleOwners must call register before they are STARTED.

    需要修改成:

    private val launcherBLE =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == RESULT_OK) {
                // granted
            } else {
                // deny
            }
    }
    
    private fun enableBluetooth() {
        val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        launcherBLE.launch(intent)
    }
    

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式