My Android app need to do some file read/write in background (inside a Service), first I use:
CoroutineScope(Dispatchers.IO).launch {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
Every single line inside the block has a warning: "Inappropriate blocking method call"
After search the problem, I think I understand 80% of it. So basically most Coroutine only has 1 thread, if it is blocked, that coroutine will have no thread to do other job. To fix this, we should wrap it inside withContext
like this:
CoroutineScope(Dispatchers.IO).launch {
withContext(Dispatchers.IO) {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
}
Android Studio still shows the warning. The post say it is just a bug in Android Studio, and this solution is fine.
What I don't understand is, withContext
is still run on Dispatchers.IO
. From the launch
block, it may seem like non-blocking, but if Dispatchers.IO
only has 1 thread and the withContext
block is run on that thread, then that thread is still blocked isn't it?
I also learned Dispatchers.IO
actually has virtually infinite threads, it just create a new one when needed. So the withContext
actually is not blocking, but if this is true, why do we need the withContext
block? The first code won't have any problem if Dispatchers.IO
can create thread when needed thus will never be blocked, right?