Android和Kotlin协程:不合适的阻塞方法调用 [英] Android and Kotlin coroutines: inappropriate blocking method call

查看:796
本文介绍了Android和Kotlin协程:不合适的阻塞方法调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程:

class Repository(
    private val assetManager: AssetManager,
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) {
    suspend fun fetchHeritagesList(): HeritageResponse = withContext(ioDispatcher) {
        try {
            // TODO Blocking method call?
            val bufferReader = assetManager.open("heritages.json").bufferedReader()
...

,我想知道为什么我在open("heritages.json")中收到警告,说Innapropriate blocking method call吗? withContext(ioDispatcher)不能解决这个问题吗?

感谢您的解释!

解决方案

在可挂函数内部查找阻塞调用的IntelliJ检查功能不足以查看Dispatchers.IO与其在withContext中的用法之间的间接级别. .这是此问题的最小复制者:

class IoTest {
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO

    suspend fun indirectRef() = withContext(ioDispatcher) {
        Thread.sleep(1) // Flagged as inappropriate blocking call
    }

    suspend fun directRef() = withContext(Dispatchers.IO) {
        Thread.sleep(1) // Not flagged
    }
}

但是,与我的情况不同,您的ioDispatcher通过构造函数公开以进行注入,因此您可以轻松地提供Dispatchers.Main而不是它,并且构成不适当的阻塞. /p>

不幸的是,我还没有听说过将正式分配器的合同正式指定为容许阻塞调用"的任何方式,因此您可以在构造函数中强制执行它.

YouTrack 上已经存在类似的问题.

I have the following class:

class Repository(
    private val assetManager: AssetManager,
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) {
    suspend fun fetchHeritagesList(): HeritageResponse = withContext(ioDispatcher) {
        try {
            // TODO Blocking method call?
            val bufferReader = assetManager.open("heritages.json").bufferedReader()
...

and I'm wondering why do I get a warning in the open("heritages.json") saying Innapropriate blocking method call? isn't the withContext(ioDispatcher) fixing that?

Thanks for the explanation!

解决方案

IntelliJ inspection that looks for blocking calls inside suspendable functions isn't powerful enough to see through a level of indirection between Dispatchers.IO and its usage in withContext. Here's a minimal reproducer of the issue:

class IoTest {
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO

    suspend fun indirectRef() = withContext(ioDispatcher) {
        Thread.sleep(1) // Flagged as inappropriate blocking call
    }

    suspend fun directRef() = withContext(Dispatchers.IO) {
        Thread.sleep(1) // Not flagged
    }
}

However, unlike in my case, your ioDispatcher is exposed for injection through the constructor so you could just as easily supply Dispatchers.Main instead of it, and that would constitute inappropriate blocking.

Unfortunately I haven't yet heard of any way to formally specify the contract of a dispatcher as "tolerating blocking calls", so that you could enforce it in the constructor.

There is already a similar issue open on YouTrack.

这篇关于Android和Kotlin协程:不合适的阻塞方法调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆