提问人:Bitwise DEVS 提问时间:12/3/2021 更新时间:12/3/2021 访问量:5915
MainScope 与 GlobalScope
MainScope vs GlobalScope
问:
GlobalScope 和 MainScope 有什么区别?
//Accessing data from Room
GlobalScope.launch {
v.tvStoreName.text = pfViewModel.getStoreName()
pageDetails.pageNumber = currentPage
pageDetails.pageSize = pageSize
pfViewModel.getTransactions(pageDetails, toolbarBuilder?.getDate()!!)
}
GlobalScope 有时会犯一个很难重现的错误。
致命异常: android.view.ViewRootImpl$CalledFromWrongThreadException:仅 创建视图层次结构的原始线程可以触摸其视图。
MainScope().launch {
var storeName = ""
withContext(Dispatchers.Default) {
storeName = pfViewModel.getStoreName()
}
v.tvStoreName.text = storeName
}
答:
GlobalScope 和 MainScope 有什么区别?
MainScope
是默认使用调度程序的,调度程序绑定到主 UI 线程。CoroutineScope
Dispatchers.Main
是在其协程上下文中没有调度程序的 a。这意味着在此作用域中启动的协程将使用调度程序,该调度程序由线程池(根据您拥有的 CPU 内核数调整大小)提供支持。GlobalScope
CoroutineScope
Dispatchers.Default
在其上下文中也没有,这意味着结构化并发不适用。其中启动的协程永远不会自动取消,因此需要手动控制。这就是为什么除非您有非常具体的需求,否则通常不鼓励使用它。GlobalScope
Job
只有创建视图层次结构的原始线程才能触及其视图。
当您尝试从主线程外部修改视图时,会发生此错误,如果您从 中启动的协程执行此操作,则会发生这种情况(因为它由单独的线程池支持)。GlobalScope
在第二个代码片段中,您使用的是 ,它仅使这部分代码在该线程池上运行,但其余部分在 UI 线程上运行。这就是为什么那里的UI更新是可以的。withContext(Dispatchers.Default)
请注意,Room 已经使用带有后台线程池的调度程序进行查询,因此您不需要像这样手动切换上下文,只需从 UI 线程调用它即可。
旁注:像这样使用是一个坏主意,因为它与 .为了正确使用它,您需要将此范围提取到变量/属性中,以便在适当的时候取消它。也就是说,使用现有范围更容易。Android 已经在具有生命周期的 Activity 等组件中提供了现成的协程范围(请参阅库)。它被称为 .您应该在此范围内启动协程,以便在销毁活动时自动取消协程。MainScope().launch { .. }
GlobalScope
lifecycle-runtime-ktx
lifecycleScope
评论
lifecycleScope
viewModelScope
viewModelScope
lifecycleScope
评论