I wrote this code in Kotlin to download some API information using Coroutines for downloading the data. However, the code shows a lot of warnings stating the message as "Inappropriate blocking method call".
Here's the code:
class DownloadInfoClass {
private lateinit var url: URL
private lateinit var httpURLConnection: HttpURLConnection
private lateinit var result: String
private lateinit var inputStream: InputStream
private lateinit var inputStreamReader: InputStreamReader
private var dataMap: MutableMap<String, Any> = mutableMapOf()
private fun downloadMethod(urls: String){
CoroutineScope(IO).launch {
try {
url = URL(urls)
httpURLConnection = url.openConnection() as HttpURLConnection
inputStream = httpURLConnection.inputStream
inputStreamReader = InputStreamReader(inputStream)
var data: Int = inputStreamReader.read()
while (data != -1){
val current: Char = data.toChar()
result += current
data = inputStreamReader.read()
}
}
catch (e: Exception){
e.printStackTrace()
}
}
Log.i("Result: ", result)
}
}
The specific areas where this problem occurs is:
URL(urls)
openConnection()
read()
Can anyone help me understand why this occurs? I read through the Kotlin documentation but I wasn't able to comprehend. Also, could you tell me how to fix this issue?
False positive: "Inappropriate blocking method call" with coroutines and Dispatchers.IO. The blockingFunc is marked as throwing IOException (that's how IDE detects "blocking calls"). But the function is called in Dispatchers.IO dedicated to such calls, so doesn't block main thread (or calling coroutine).
A coroutine is a concurrency design pattern that you can use on Android to simplify code that executes asynchronously. Coroutines were added to Kotlin in version 1.3 and are based on established concepts from other languages.
The problem is, that coroutines are built to only suspend and not block a thread. This means, that multiple coroutines can run on the same thread. When using blocking methods, they block the whole thread and will probably prevent other coroutines from running. So, it usually is bad practice to do this.
Since you obviously need to call these methods, use a dispatcher that tries to create a new thread for every coroutine, like Dispatchers.IO
(which is designed for those operations, see the documentation). To do so, just wrap the blocking calls with withContext
.
withContext(Dispatchers.IO) {
// your blocking calls
}
I hope I could help!
To get rid of the warning try to use next code inside DownloadInfoClass
:
private fun downloadMethod(urls: String) = CoroutineScope(Main).launch {
url = URL(urls)
val result = download() // suspends a coroutines launched using Main Context
Log.i("Result: ", result)
}
private suspend fun download() = withContext(IO) { // download on background thread
try {
httpURLConnection = url.openConnection() as HttpURLConnection
inputStream = httpURLConnection.inputStream
inputStreamReader = InputStreamReader(inputStream)
var data: Int = inputStreamReader.read()
while (data != -1) {
val current: Char = data.toChar()
result += current
data = inputStreamReader.read()
}
result // return result if there are no Exceptions
} catch (e: Exception) {
e.printStackTrace()
}
"" // return empty String if there is an Exception
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With