Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can anyone explain why these "Inappropriate blocking method call" warnings pop up from my code?

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:

  1. URL(urls)
  2. openConnection()
  3. 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?

like image 543
Arpan Sircar Avatar asked Jul 07 '20 07:07

Arpan Sircar


People also ask

What is inappropriate blocking method call?

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).

What are coroutines in Android?

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.


2 Answers

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!

like image 195
theincxption Avatar answered Oct 19 '22 21:10

theincxption


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
}
like image 45
Sergey Avatar answered Oct 19 '22 22:10

Sergey