如何使“不合适的阻塞方法调用”合适?

时间:2019-11-03 12:11:39

标签: kotlin okhttp kotlin-coroutines moshi

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

“不合适的阻止方法调用”

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

7 个答案:

答案 0 :(得分:27)

调用挂起函数@Throws(IOException::class)(Kotlin 1.3.61)时,也会收到此警告。不知道这是否是故意的。无论如何,您可以通过删除该注释或将其更改为Exception类来禁止显示此警告。

答案 1 :(得分:26)

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

例如:

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

答案 2 :(得分:17)

包装其他上下文中使用 {{1将“不适当的阻止方法调用” 代码 }}

也就是说(例如):

如果您正在执行读/写阻止方法调用:

withContext

如果您正在执行阻止网络请求(使用翻新):

val objects = withContext(Dispatchers.IO) { dao.getAll() }

或者如果您正在执行CPU密集型阻止任务:

val response = withContext(Dispatchers.IO) { call.execute() }

这将挂起当前的协程,然后在不同的线程(来自val sortedUsers = withContext(Dispatchers.Default) { users.sortByName() } Dispatchers.IO池)上执行“不适当的阻塞调用” >不阻止您的协程在其上执行的线程。

答案 3 :(得分:2)

如果您确实像某些答案所建议的那样选择抑制,请使用

@Suppress("BlockingMethodInNonBlockingContext")

答案 4 :(得分:1)

警告是关于无法正确暂停阻止当前线程和协程的方法。这样,您将失去协程的所有好处,并再次将每个线程降级为一项工作。

每种情况应以不同的方式处理。对于可挂起的http呼叫,您可以使用ktor http client。但是有时您的案例没有库,因此您可以编写自己的解决方案或忽略此警告。

答案 5 :(得分:0)

我正在使用Android Studio 4.1,当我使用Moshi或操纵File时会显示警告。即使我确定自己在做什么,也无法将代码包装在withContext中。

我最近发现,将发出警告的小代码移入没有suspend之类的fun action() {...}的标准方法中,可以消除警告。这有点难看,因为它隐藏了警告。

答案 6 :(得分:-1)

我使用调度程序作为启动参数:

    GlobalScope.launch(Dispatchers.IO) {
        // Do background work
        
        // Back to main thread
        launch(Dispatchers.Main) {
            Toast.makeText(context, "SUCCESS!", Toast.LENGTH_LONG)
                .show()
        }
    }