英文:
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ánh nhiều yêu cầu
if(permissionContinuation != null)
return null
// requestPermissionを実行
val device = suspendCoroutine<UsbDevice?> {
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<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
}
}
}
}
} 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,
"Success get permission for device ${usbDevice?.deviceId}, vendor_id: ${usbDevice?.vendorId} product_id: ${usbDevice?.productId}"
)
mUsbDevice = usbDevice
openConnection()
permissionContinuation!!.resume(usbDevice)
state = STATE_USB_CONNECTED
mHandler?.obtainMessage(STATE_USB_CONNECTED)?.sendToTarget()
} else {
permissionContinuation!!.resume(null)
Toast.makeText(context, "User refused to give USB device permission: ${usbDevice?.deviceName}", 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, "USB device has been turned off", 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
值会直接返回(而不是通过回调、Future
或 Deferred
返回)。
然而,在这个函数内部,你尝试启动一个异步任务(使用 launch
函数),但你却希望从中返回结果。这不是 launch
的工作方式。因为任务是异步的,调用 launch
的调用会在任务完成之前返回,甚至在任务开始之前就返回。正如我们上面所看到的,launch
本身不返回任何值。实际上,即使你将其更改为 async
,async { .. }
函数调用也不会直接返回值,而是返回一个 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<Boolean>
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<Boolean>
(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() }
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论