Android和Kotlin协程:不合适的阻塞方法调用 [英] Android and Kotlin coroutines: inappropriate blocking method call
问题描述
我有以下课程:
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屋!