我目前正在尝试更多地利用kotlin协程。但我面临一个问题:当在这些协程中使用moshi或okhttp时,我得到一个警告:
“不恰当的阻塞方法调用”
解决这些问题的最好方法是什么?我真的不想不合适;-)
我目前正在尝试更多地利用kotlin协程。但我面临一个问题:当在这些协程中使用moshi或okhttp时,我得到一个警告:
“不恰当的阻塞方法调用”
解决这些问题的最好方法是什么?我真的不想不合适;-)
当前回答
我今天遇到了同样的问题,下面的解决方案对我来说很有效。希望能有所帮助!
CoroutineScope(Dispatchers.IO).launch {
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
print("Internet access, 4G, Wifi, DNS, etc failed")
}
override fun onResponse(call: Call, response: Response) {
if(response.isSuccessful) {
print("Server accepted!")
} else {
print("Server failed!")
}
}
})
}
请记住,这个回调函数只被使用一次。你不能在其他线程中使用它。
其他回答
我使用dispatchers作为启动参数:
GlobalScope.launch(Dispatchers.IO) {
// Do background work
// Back to main thread
launch(Dispatchers.Main) {
Toast.makeText(context, "SUCCESS!", Toast.LENGTH_LONG)
.show()
}
}
可能会发生异常,这就是为什么会显示此警告。使用runCatching{}。它捕获从块函数执行中抛出的任何Throwable异常,并将其封装为失败。
例如:
CoroutineScope(Dispatchers.IO).launch {
runCatching{
makeHttpRequest(URL(downloadLocation))
}
}
一个解决方案是通过挂起有趣的kotlinx. corroutine . runinterruptible来包装阻塞代码。 如果没有它,当协程的任务被取消时,阻塞代码将不会中断。
它抑制了编译警告,阻塞代码将在取消时抛出InterruptedException
val job = launch {
runInterruptible(Dispatchers.IO) {
Thread.sleep(500) // example blocking code
}
}
job.cancelAndJoin() // Cause will be 'java.lang.InterruptedException'
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-interruptible.html
如何将Java阻塞函数转换为可取消的挂起函数?
这就是如何挂起协程,在线程中运行阻塞方法,并在结果上恢复它。这也将处理异常,所以你的应用程序不会崩溃。
suspendCoroutine { continuation ->
thread {
try {
doHttpRequest(URL(...)) {
continuation.resume(it)
}
}
catch (t: Throwable) {
continuation.resumeWithException(t)
}
}
}
编辑:预期的方法是使用witchContext(Dispatchers.IO)。我把这个回答留在这里,以防有人发现这种方法有用。
我使用Android Studio 4.1,当我使用Moshi或操作文件时,警告显示。即使我确定我在做什么,在withContext中包装代码也没有帮助。
我最近发现,将警告的小代码移动到标准方法中,而不像有趣的action(){…}可以删除警告。这很难看,因为它只是隐藏了警告。
更新:从我的个人经验来看,似乎抑制警告或runBlocking更直接。