我目前正在尝试更多地利用kotlin协程。但我面临一个问题:当在这些协程中使用moshi或okhttp时,我得到一个警告:

“不恰当的阻塞方法调用”

解决这些问题的最好方法是什么?我真的不想不合适;-)


当前回答

这就是如何挂起协程,在线程中运行阻塞方法,并在结果上恢复它。这也将处理异常,所以你的应用程序不会崩溃。

suspendCoroutine { continuation ->
    thread {
        try {
            doHttpRequest(URL(...)) {
                continuation.resume(it)
            }
        }
        catch (t: Throwable) {
            continuation.resumeWithException(t)
        }
    }
}

编辑:预期的方法是使用witchContext(Dispatchers.IO)。我把这个回答留在这里,以防有人发现这种方法有用。

其他回答

如果你选择像一些答案建议的那样压抑,那就使用

@Suppress(“BlockingMethodInNonBlockingContext”)

我使用Android Studio 4.1,当我使用Moshi或操作文件时,警告显示。即使我确定我在做什么,在withContext中包装代码也没有帮助。

我最近发现,将警告的小代码移动到标准方法中,而不像有趣的action(){…}可以删除警告。这很难看,因为它只是隐藏了警告。

更新:从我的个人经验来看,似乎抑制警告或runBlocking更直接。

可能会发生异常,这就是为什么会显示此警告。使用runCatching{}。它捕获从块函数执行中抛出的任何Throwable异常,并将其封装为失败。

例如:

 CoroutineScope(Dispatchers.IO).launch {
         runCatching{
               makeHttpRequest(URL(downloadLocation))
         }
}

当调用带有@Throws(IOException::class)注释的挂起函数(Kotlin 1.3.61)时,也会收到此警告。不确定这是否是有意为之。无论如何,您可以通过删除该注释或将其更改为Exception类来抑制此警告。

我今天遇到了同样的问题,下面的解决方案对我来说很有效。希望能有所帮助!

        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!")
                }
            }
        })
    }

请记住,这个回调函数只被使用一次。你不能在其他线程中使用它。