Search code examples
androidapikotlinkotlin-coroutinescoroutinescope

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?


Solution

  • 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!