我有一個方法可以連續運行一些操作。Is 實際上是一個 for 回圈,它將其內容回圈 50 次,每次迭代大約需要 0.2 秒。在此執行期間,我在螢屏上顯示了一個恒定的影片。因此,很明顯我希望將這些操作從主執行緒中轉移出去,這樣我的影片就可以跟上(或者可以進行重組,這就是 Compose)。我意識到,這個簡單的方法
fun run(){
repeat(10000) {
repeat(5000){
print("I ? Kotlin")
}
}
}
如果像這樣在標準的 Composable 范圍內運行,則會像預期的那樣阻塞 UI 執行緒。
b)如果我在呼叫它時將它LaunchedEffect嵌套在對launch{...}.
c) 如果我在 I/O 協程(也是默認協程)上運行它,它不會阻塞。
d) 如果在 Main Dispatcher 上運行,應用程式有時會崩潰
現在,一個簡單的問題——為什么會這樣?
LaunchedEffect(Unit){
run() // Block
}
Launchedeffect(Unit){
launch{
run() // Block
}
}
LaunchedEffect(Unit){
withContext(Dispatchers.Main){
run() //Blocks, and at times, crashes
}
}
LaunchedEffect(Unit){
withContext(Dispatchers.IO){
run() // Runs without blocking
}
}
thread{
run() //Runs without blocking, no crash
}
誰能解釋為什么這些Dispatchers.IO作品和其他作品沒有?這有點給我帶來了不希望的壓力。
如果有人需要一個快速的影片 UI 來測驗它,這里就是
@Composable
fun DUM_E_MARK_II() {
val sizeTransition = rememberInfiniteTransition()
val size by sizeTransition.animateFloat(
initialValue = 50f,
targetValue = 200f,
animationSpec = infiniteRepeatable(
keyframes { durationMillis = 1000 },
repeatMode = RepeatMode.Reverse,
)
)
Icon(
imageVector = Icons.Filled.Warning,
contentDescription = "",
modifier = Modifier.size(size.dp),
tint = Color.Red
)
}
uj5u.com熱心網友回復:
您的代碼是一項長期運行的、不可暫停的任務。它會在其整個生命周期內阻止它運行的任何執行緒。當你阻塞 UI 執行緒時,它會導致 UI 凍結,并且在超時后,Android 會殺死這樣一個行為不端的應用程式。
如果您使用任何使用其自己的執行緒池的調度程式,例如 IO,該任務將阻塞非 UI 執行緒。
uj5u.com熱心網友回復:
withContext(Dispatchers.IO){
run() // Runs without blocking
}
在這里,你明確地說你想在另一個執行緒上運行它,特別是一個不會對主執行緒產生影響的執行緒,所以當你呼叫時:
withContext(Dispatchers.Main){
run() //Blocks, and at times, crashes
}
那么是的,這可能會因 ANR 例外而崩潰,因為主執行緒已被阻塞太久,這就是withContext 的重點是指定應該在哪里完成這項作業,并且不應執行密集或長時間運行的任務Dispatchers.Main
此函式使用來自新背景關系的調度程式,如果指定了新的調度程式,則將塊的執行轉移到不同的執行緒,并在完成時回傳原始調度程式。
uj5u.com熱心網友回復:
run()函式是一個長時間運行的函式,它會阻塞執行它的執行緒。
讓我們一一考慮每種情況:
run()在Main(UI) 執行緒中呼叫函式,阻止它。LaunchedEffect(Unit) { run() // Block }run()在協程中呼叫,該協程使用launch協程構建器啟動。協程的背景關系是組合的CoroutineContext,我假設它由Dispatchers.Main調度程式組成。所以該run函式也在Main(UI) 執行緒中被呼叫,阻塞它。Launchedeffect(Unit) { launch { run() // Block } }
您可以使用來創建run()函式,它將函式的執行背景關系切換到執行緒池:suspendwithContext(Dispatchers.IO)runDispatchers.IO
suspend fun run() = withContext(Dispatchers.IO) {
// this is executed in background thread
}
Launchedeffect(Unit) {
run() // Not Blocking
}
Launchedeffect(Unit) {
launch {
run() // Not Blocking
}
}
run()函式在Main(UI) 執行緒中被呼叫,阻塞它,因為Dispatchers.Main它被用于它的背景關系執行。在Main(UI) 執行緒Dispatchers.Main中執行協程。LaunchedEffect(Unit){ withContext(Dispatchers.Main){ run() // Blocks, and at times, crashes } }在這種情況下,它會在沒有阻塞的情況下運行,因為
Dispatchers.IO它被用作協程背景關系。它使用后臺執行緒池。它不會阻塞主執行緒,因為它在后臺執行緒中執行。LaunchedEffect(Unit){ withContext(Dispatchers.IO){ run() // Runs without blocking } }這在不阻塞主執行緒的情況下運行,因為另一個執行緒(后臺執行緒)用于執行它。
thread{ run() //Runs without blocking, no crash }
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/433071.html
標籤:安卓 多线程 科特林 android-jetpack-compose kotlin 协程
