'Coroutines, dispatchers, and inappropriate blocking methods

I wrote an app that basically does a lot of IO in response to user prompts. It seems to work fine, but Android Studio complains that all its IO method invocations are "Inappropriate blocking methods."

I tried to follow the official recommendations (here and here), so I used coroutines and wrapped all my IO calls inside withContext(Dispatchers.IO), but Android Studio still insists that they're all "Inappropriate blocking methods."

Minimal reproducible example (see here):

package com.example.blockingtest

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.FileInputStream

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        CoroutineScope(Dispatchers.Main).launch { mySuspendFunction() }
    }
    private suspend fun mySuspendFunction() {
        withContext(Dispatchers.IO) { FileInputStream("dummy.txt") }
    }
}

Android Studio flags the FileInputStream call as "Inappropriate blocking method."

I found numerous discussions of this sort of thing here on Stack Overflow and elsewhere, but no correct solution or satisfying explanation:

  • This accepted Stack Overflow answer is either wrong or outdated, as its author has conceded in an edit.
  • This Stack Overflow answer, this one, this accepted one (in an edit), and this accepted one all assert that withContext(Dispatchers.IO) wrapping is the solution; it doesn't stop Android Studio's warnings, as above.
  • This Stack Overflow answer and this one assert that the problem is that the methods in question can throw exceptions, but there's no real explanation of why that possibility should trigger an "Inappropriate blocking method" warning. Furthermore, one suggestion is to wrap the calls inside runCatching {}. This does indeed stop Android Studio's complaining, but as one of the comments notes, classic try / catch semantics do not help. I don't understand this at all.
  • Some suggest suppressing the warning. I'd like a real solution or explanation.
  • Another Stack Overflow discussion, with no real solution, and another one, also with no working solution.
  • Other discussions: here, here. No solutions / explanations of Android Studio's behavior that I noticed.

Is Android Studio just badly broken in this area, as some have asserted in the linked discussions? I've learned over the years that whenever I think the tools are making a mistake, it's definitely my error, but is this one really Android Studio bugginess?



Solution 1:[1]

FileInputStream(..) is a thread blocking function and there's nothing you can about it. Calling it in withContext(Dispatchers.IO) is indeed the proper way to handle it as Dispatchers.IO can have unlimited number of actual threads (capped by hardware or ART). Thus, if one thread is blocked coroutines can run in an other thread.

If the problem is the warning after you wrapped the call in withContext(Dispatchers.IO), the only thing you can do about it is to either suppress it or wait for a Kotlin update where the IDE will recognize correctly that you have already handled the call as you were supposed to.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rtsketo