Android 和 Kotlin 协程:不适当的阻塞方法调用

nol*_*man 20 android kotlin kotlin-coroutines

我有以下课程:

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()
...
Run Code Online (Sandbox Code Playgroud)

open("heritages.json")我想知道为什么我会在这句话中收到警告Innapropriate blocking method call?修复不是withContext(ioDispatcher)这样的吗?

感谢您的解释!

Mar*_*nik 29

检查的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
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,与我的情况不同,您ioDispatcher通过构造函数暴露以供注入,因此您可以轻松地提供Dispatchers.Main而不是它,这构成不适当的阻塞。

不幸的是,我还没有听说有任何方法可以将调度程序的合同正式指定为“容忍阻塞调用”,以便您可以在构造函数中强制执行它。

YouTrack上已经有一个类似的问题。

  • 我刚刚向你展示了它是。也许您使用的是较新版本的 IDE。我使用“Android Studio 4.2 Beta 4 Build #AI-202.7660.26.42.7094744,构建于2021年1月21日运行时版本:11.0.8+10-b944.6842174 amd64” (4认同)
  • 第二个实际上已标记:https://i.imgur.com/UdfcQ6y.png (3认同)