[英]Main Thread used when using coroutine IO Thread in Kotlin
我正在嘗試使用 Volley 和 HTTPURLConnection 從服務器獲取數據。 使用協程IO Thread來防止阻塞主線程,但在執行作業時屏幕停止(這意味着主線程被阻塞)。
奇怪的是,它在使用 Jsoup 和 HTTPURLConnection 做其他工作時完美地工作。 我能找到的唯一區別是它不使用 lambda。
可能是什么問題呢? 提前致謝。
*Edit1:我使用了 suspend 和 withContext,但我發現刪除它們並不能解決問題。
ConDetailActivity.kt 代碼
val scope = CoroutineScope(Dispatchers.IO)
private fun initialize(context: Context,idx:String) = scope.launch{
try{
ConCrawler.getConData(context,idx) {data ->
CoroutineScope(Dispatchers.Main).launch { adapter.addData(data.imgDataList) }
progressbar.visibility = View.INVISIBLE
}
}catch(e:Exception){
e.printStackTrace()
}
}
對象 ConCrawler 代碼
suspend fun getConData(context: Context, idx: String, returnConData: (condata: ConDataforReturn) -> Unit) = withContext(Dispatchers.Default) {
val params = HashMap<String, String>()
val cd = arrayListOf<ConImgData?>()
var title = ""
params.put("package_idx", idx)
VolleyRequest(context, params, "https://dccon.dcinside.com/index/package_detail") { response ->
val answer = JSONObject(response)
var json = answer.getJSONArray("detail")
title = answer.getJSONObject("info").getString("title")
for (i in 0..(json.length() - 1)) {
val v = json.getJSONObject(i)
cd.add(ConImgData(v.getString("title"), v.getString("ext"), runBlocking { getBitmapFromURL("https://dcimg5.dcinside.com/dccon.php?no=" + v.getString("path")) }, v.getString("path")))
}
returnConData(ConDataforReturn(title, cd))
}
}
fun VolleyRequest(context: Context, params: HashMap<String, String>, link: String, success: (response: String) -> Unit) {
val queue = Volley.newRequestQueue(context)
val stringRequest = object : StringRequest(Method.POST, link,
Response.Listener<String> { response ->
Log.e("response", response.toString())
success(response)
},
Response.ErrorListener { error ->
error.printStackTrace()
}) {
override fun getHeaders(): MutableMap<String, String> {
val headers = mutableMapOf<String, String>()
/*unused headers
headers.put("user-agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36")
headers.put("origin","https://dccon.dcinside.com")
headers.put("referer","https://dccon.dcinside.com")
headers.put("content-type","multipart/form-data")
*/
headers.put("x-requested-with", "XMLHttpRequest")
return headers
}
override fun getParams(): MutableMap<String, String> {
return params
}
}
stringRequest.setShouldCache(false)
queue.add(stringRequest)
}
suspend fun getBitmapFromURL(src: String): Bitmap? = withContext(Dispatchers.Default) {
try {
val url = URL(src)
val connection: HttpURLConnection = url.openConnection() as HttpURLConnection
connection.setRequestProperty("Referer", "https://dccon.dcinside.com")
connection.setRequestProperty("Sec-Fetch-Mode", "no-cors")
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36")
connection.setDoInput(true)
connection.connect()
val input: InputStream = connection.getInputStream()
BitmapFactory.decodeStream(input)
} catch (e: Exception) { // Log exception
e.printStackTrace()
null
}
}
找到了解決辦法。 關鍵是兩種情況的區別。
問題是 lambda。 使用 lambda 時,會創建新塊,並且該塊與外部塊分開。 這意味着 lambda 塊在主線程中再次運行。
所以在 lambda 塊中再次創建協程解決了這個問題。 希望這對其他新手有所幫助。
fun getConData(context: Context, idx: String, returnConData: (condata: ConDataforReturn) -> Unit) {
val params = HashMap<String, String>()
val cd = arrayListOf<ConImgData?>()
var title = ""
params.put("package_idx", idx)
VolleyRequest(context, params, "https://dccon.dcinside.com/index/package_detail") { response ->
CoroutineScope(Dispatchers.IO).launch {
val answer = JSONObject(response)
var json = answer.getJSONArray("detail")
title = answer.getJSONObject("info").getString("title")
for (i in 0..(json.length() - 1)) {
val v = json.getJSONObject(i)
var a = getBitmapFromURL("https://dcimg5.dcinside.com/dccon.php?no=" + v.getString("path"))
cd.add(ConImgData(v.getString("title"), v.getString("ext"), a, v.getString("path")))
}
returnConData(ConDataforReturn(title, cd))
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.