[英]lifecycleScope.launch vs coroutine inside onViewCreated
[英]Kotlin Coroutine launch{} vs launch{ withContext{} }
我的 Android 應用程序需要在后台(在服務內)進行一些文件讀/寫,首先我使用:
CoroutineScope(Dispatchers.IO).launch {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
塊內的每一行都有一個警告:“不適當的阻塞方法調用”
搜索問題后,我認為我理解了 80%。 所以基本上大多數協程只有1個線程,如果它被阻塞,協程將沒有線程來做其他工作。 要解決這個問題,我們應該像這樣將它包裝在withContext
:
CoroutineScope(Dispatchers.IO).launch {
withContext(Dispatchers.IO) {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
}
Android Studio 仍然顯示警告。 帖子說這只是 Android Studio 中的一個錯誤,這個解決方案很好。
我不明白的是, withContext
仍在Dispatchers.IO
上運行。 從launch
塊來看,它可能看起來像非阻塞,但如果Dispatchers.IO
只有 1 個線程並且withContext
塊在該線程上運行,那么該線程仍然被阻塞,不是嗎?
我還了解到Dispatchers.IO
實際上有無限線程,它只是在需要時創建一個新線程。 所以withContext
實際上並沒有阻塞,但如果這是真的,為什么我們需要withContext
塊? 如果Dispatchers.IO
可以在需要時創建線程從而永遠不會被阻塞,那么第一個代碼不會有任何問題,對吧?
是的,這是一個帶有警告的錯誤。 Lint 無法檢測到 scope 使用的是什么 Dispatcher,我想他們只是假設您使用的是 scope,其上下文使用Dispatchers.Main
,因為這是最常見的。
您的 CoroutineScope(偽)構造函數具有Dispatchers.IO
的上下文,因此如果不修改它, launch
會繼承該上下文,因此您啟動的協程也使用Dispatchers.IO
。 所以,你的withContext
塊是多余的。
解決方法是在啟動時指定調度程序:
CoroutineScope(Job()).launch(Dispatchers.IO) {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
另外,你的聲明:
所以基本上大多數協程只有1個線程,如果它被阻塞,協程將沒有線程來做其他工作。
具有誤導性。 協程沒有線程,而 Dispatcher 有。 並且有些 Dispatcher 有很多線程。
似乎 Android Studio 中確實存在錯誤。 以下代碼對我沒有顯示任何警告:
CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
val fos = context.openFileOutput("", Context.MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
您還應該知道,這段代碼與您共享的兩段代碼在行為上幾乎沒有區別。 在這三種情況下,代碼都將在 IO 線程上執行。
CoroutineScope(context)
launch(context)
withContext(context
所有這些方法都只是指定協程上下文。 默認情況下, launch
使用協程 scope 上下文,但您可以像我上面所做的那樣或使用withContext
來更改它。
所以基本上大多數協程只有1個線程,如果它被阻塞,協程將沒有線程來做其他工作。
Dispatchers.IO
實際上默認為 64 個線程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.