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

发布时间: 2022-10-29 22:05:36 作者: 大象笔记

举两个例子

例子一:开启蓝牙

废弃的 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)
}
我是一名山东烟台的开发者,联系作者