如何在使用 Kotlin 协程时返回布尔值

huangapple go评论56阅读模式
英文:

How to return boolean when using coroutines kotlin

问题

我在运行代码时遇到错误:布尔字面值不符合预期的Unit类型。请帮助我修复它。

public suspend fun RequireDevice(manager: UsbManager, device: UsbDevice): UsbDevice? {
    if (permissionContinuation != null)
        return null

    val device = suspendCoroutine<UsbDevice?> {
        manager.requestPermission(device, mPermissionIndent)
        permissionContinuation = it
    }

    permissionContinuation = null
    return device
}

fun selectDevice(vendorId: Int, productId: Int): Boolean {
    if ((mUsbDevice == null) || (mUsbDevice!!.vendorId != vendorId) || (mUsbDevice!!.productId != productId)) {
        closeConnectionIfExists()
        connectScope.launch label@{
            val usbDevices: List<UsbDevice> = deviceList
            for (usbDevice: UsbDevice in usbDevices) {
                if ((usbDevice.vendorId == vendorId) && (usbDevice.productId == productId)) {
                    Log.v(LOG_TAG, "Request for device: vendor_id: " + usbDevice.vendorId + ", product_id: " + usbDevice.productId)
                    closeConnectionIfExists()
                    val grantedDevice = RequireDevice(mUSBManager!!, usbDevice)
                    if (grantedDevice != null) {
                        Log.v(LOG_TAG, "Connected")
                        state = STATE_USB_CONNECTING
                        mHandler?.obtainMessage(STATE_USB_CONNECTING)?.sendToTarget()
                        return@label true
                    } else {
                        Log.v(LOG_TAG, "Connection failed.")
                        return@label false
                    }
                }
            }
        }
        return false // 添加此行以修复错误
    } else {
        mHandler?.obtainMessage(state)?.sendToTarget()
        return true
    }
}

希望以上修复能够解决你遇到的问题。如果还有其他问题,请告诉我。

英文:

I get the error The boolean literal does not conform to the expected type Unit when run code. Please help me fix it

public suspend fun RequireDevice(manager: UsbManager, device: UsbDevice): UsbDevice? {
    // 多重要求にならないようにする - Tr&#225;nh nhiều y&#234;u cầu
    if(permissionContinuation != null)
        return null
    // requestPermissionを実行
    val device = suspendCoroutine&lt;UsbDevice?&gt; {
        manager.requestPermission(device, mPermissionIndent)
        permissionContinuation = it
    }
    // continuationを消去
    permissionContinuation = null
    return device
}

function selectDevice

fun selectDevice(vendorId: Int, productId: Int): Boolean {
    if ((mUsbDevice == null) || (mUsbDevice!!.vendorId != vendorId) || (mUsbDevice!!.productId != productId)) {
        closeConnectionIfExists()
        connectScope.launch label@{
            val usbDevices: List&lt;UsbDevice&gt; = deviceList
            for (usbDevice: UsbDevice in usbDevices) {
                if ((usbDevice.vendorId == vendorId) &amp;&amp; (usbDevice.productId == productId)) {
                    Log.v(LOG_TAG, &quot;Request for device: vendor_id: &quot; + usbDevice.vendorId + &quot;, product_id: &quot; + usbDevice.productId)
                    closeConnectionIfExists()
                    val grantedDevice = RequireDevice(mUSBManager!!, usbDevice)
                    if (grantedDevice != null){
                        Log.v(LOG_TAG, &quot;Connected&quot;)
                        state = STATE_USB_CONNECTING
                        mHandler?.obtainMessage(STATE_USB_CONNECTING)?.sendToTarget()
                        return@label true
                    }  
                    else{
                        Log.v(LOG_TAG, &quot;Connection failed.&quot;)
                        return@label false
                    } 
                }
            }
        }
    } else {
        mHandler?.obtainMessage(state)?.sendToTarget()
        return true
    } 
}

BroadcastReceiver

private val mUsbDeviceReceiver: BroadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val action = intent.action
        if ((ACTION_USB_PERMISSION == action)) {
            synchronized(this) {
                val usbDevice: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    Log.i(
                        LOG_TAG,
                        &quot;Success get permission for device ${usbDevice?.deviceId}, vendor_id: ${usbDevice?.vendorId} product_id: ${usbDevice?.productId}&quot;
                    )
                    mUsbDevice = usbDevice
                    openConnection()
                    permissionContinuation!!.resume(usbDevice)
                    state = STATE_USB_CONNECTED
                    mHandler?.obtainMessage(STATE_USB_CONNECTED)?.sendToTarget()
                } else {
                    permissionContinuation!!.resume(null)
                    Toast.makeText(context, &quot;User refused to give USB device permission: ${usbDevice?.deviceName}&quot;, Toast.LENGTH_LONG).show()
                    state = STATE_USB_NONE
                    mHandler?.obtainMessage(STATE_USB_NONE)?.sendToTarget()
                }
            }
        } else if ((UsbManager.ACTION_USB_DEVICE_DETACHED == action)) {

            if (mUsbDevice != null) {
                Toast.makeText(context, &quot;USB device has been turned off&quot;, Toast.LENGTH_LONG).show()
                closeConnectionIfExists()
                state = STATE_USB_NONE
                mHandler?.obtainMessage(STATE_USB_NONE)?.sendToTarget()
            }

        } else if ((UsbManager.ACTION_USB_DEVICE_ATTACHED == action)) {
        }
    }
}

Error:

e:USBPrinterService.kt: (139, 42): The boolean literal does not conform to the expected type Unit

Error 2:
e:USBPrinterService.kt: (143, 42): The boolean literal does not conform to the expected type Unit
Error 3:
e:USBPrinterService.kt: (154, 5): A 'return' expression required in a function with a block body ('{...}')

答案1

得分: 3

"boolean literal does not conform to the expected type Unit"

你遇到这个错误是因为传递给 launch 的 lambda 不应返回任何有用的值。它的返回类型是 Unit,用于那些不期望有特定结果的函数,而你尝试返回一个 Boolean,与返回类型不匹配。

要返回一个值,你需要使用 async 而不是 launch。这样,lambda 确实可以返回一个值(在这里是 Boolean),而 async 函数本身将返回一个代表将在任务完成时获取的未来布尔值的 Deferred<Boolean>。然而,这里有一个更深层次的问题需要你先理解。

你必须理解这个函数签名表示一个同步函数:

fun selectDevice(vendorId: Int, productId: Int): Boolean {
   ...
}

这意味着它会阻塞调用线程,直到结果返回,因为它不是 suspend 函数,而且 Boolean 值会直接返回(而不是通过回调、FutureDeferred 返回)。

然而,在这个函数内部,你尝试启动一个异步任务(使用 launch 函数),但你却希望从中返回结果。这不是 launch 的工作方式。因为任务是异步的,调用 launch 的调用会在任务完成之前返回,甚至在任务开始之前就返回。正如我们上面所看到的,launch 本身不返回任何值。实际上,即使你将其更改为 asyncasync { .. } 函数调用也不会直接返回值,而是返回一个 Deferred<Boolean>(正如我们所见)。这个包装器会立即返回(在任务完成或甚至开始之前),所以你仍然必须以某种方式等待这个值准备好。

基本上,你选择的 selectDevice 签名要求你不得不阻塞当前线程,直到值准备好,这有点违背协程的目的。相反,最好将 selectDevice 本身定义为 suspend 函数,这样你就可以在其中调用挂起函数而不启动新的协程。

如果你想坚持使用阻塞式签名,那么你必须阻塞线程以等待该值,例如使用 runBlocking { deferred.await() }

英文:

> The boolean literal does not conform to the expected type Unit

You're facing this error because the lambda passed to launch is not expected to return any useful value. Its return type is Unit, which is used in functions for which we don't expect any particular result, and you're trying to return a Boolean out of it, which doesn't match the return type.

In order to return a value, you would need to use async instead of launch. This way, the lambda can indeed return a value (here, a Boolean), and the async function itself will return a Deferred&lt;Boolean&gt; representing the future boolean value that will get when the task completes. However, there is a deeper problem here that you need to understand first.

You have to understand that this function signature denotes a synchronous function:

fun selectDevice(vendorId: Int, productId: Int): Boolean {
   ...
}

It means it blocks the calling thread until the result is returned, because it's not suspend and the Boolean value is returned directly (not via a callback or a Future or Deferred).

However, inside this function, you're trying to launch an asynchronous task (with the launch function), but you somehow still want to return the result from it. That's not how launch works. Because the task is asynchronous, the call to launch returns before the task is completed, and possibly even before the task starts at all. As we've also seen above, launch doesn't return any value itself. In fact, even if you change it to async, the async { .. } function call will not return the value directly, but a Deferred&lt;Boolean&gt; (as we've seen). This wrapper would be returned immediately (before the task completes or even starts), so you would then have to wait for this value to be ready somehow anyway.

Basically, with the signature you chose for selectDevice, you don't have a choice but to block the current thread until the value is ready, which kinda defeats the purpose of coroutines. Instead, it would be best if you made selectDevice a suspend function itself, so you can call suspend functions inside without launching new coroutines.

If you want to stick with the blocking signature, then you have to block the thread to wait for the value, for instance using runBlocking { deferred.await() }.

huangapple
  • 本文由 发表于 2023年1月9日 18:09:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75055725.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定