谁能解释为什么这些 "Inappropriate blocking method call" 警告会从我的代码中弹出?
Can anyone explain why these "Inappropriate blocking method call" warnings pop up from my code?
我在 Kotlin 中编写了这段代码,以使用协程下载一些 API 信息来下载数据。但是,代码显示了很多警告,将消息声明为“不适当的阻塞方法调用”。
代码如下:
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)
}
}
出现此问题的具体区域是:
URL(urls)
openConnection()
read()
谁能帮我理解为什么会这样?我通读了 Kotlin 文档,但无法理解。另外,你能告诉我如何解决这个问题吗?
要消除警告,请尝试使用 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
}
问题是,协程被构建为仅 suspend 而不会阻塞线程。这意味着,多个协程可以 运行 在同一个线程上。当使用阻塞方法时,它们会阻塞整个线程并且可能会阻止其他协程 运行ning。所以,这样做通常是不好的做法。
由于您显然需要调用这些方法,因此请使用尝试为每个协程创建一个新线程的调度程序,例如 Dispatchers.IO
(专为这些操作而设计,请参阅 documentation) .为此,只需用 withContext
.
包装阻塞调用
withContext(Dispatchers.IO) {
// your blocking calls
}
希望能帮到你!
我在 Kotlin 中编写了这段代码,以使用协程下载一些 API 信息来下载数据。但是,代码显示了很多警告,将消息声明为“不适当的阻塞方法调用”。
代码如下:
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)
}
}
出现此问题的具体区域是:
URL(urls)
openConnection()
read()
谁能帮我理解为什么会这样?我通读了 Kotlin 文档,但无法理解。另外,你能告诉我如何解决这个问题吗?
要消除警告,请尝试使用 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
}
问题是,协程被构建为仅 suspend 而不会阻塞线程。这意味着,多个协程可以 运行 在同一个线程上。当使用阻塞方法时,它们会阻塞整个线程并且可能会阻止其他协程 运行ning。所以,这样做通常是不好的做法。
由于您显然需要调用这些方法,因此请使用尝试为每个协程创建一个新线程的调度程序,例如 Dispatchers.IO
(专为这些操作而设计,请参阅 documentation) .为此,只需用 withContext
.
withContext(Dispatchers.IO) {
// your blocking calls
}
希望能帮到你!