簡體   English   中英

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是一個CoroutineScope ,默認使用Dispatchers.Main調度器,綁定到主 UI 線程。

GlobalScope是一個CoroutineScope ,它的協程上下文中沒有調度程序。 這意味着在此 scope 中啟動的協程將使用Dispatchers.Default調度程序,該調度程序由線程池支持(大小取決於您擁有的 CPU 內核數量)。

GlobalScope在其上下文中也沒有Job ,這意味着結構化並發不適用。 其中啟動的協程永遠不會自動取消,因此需要手動控制。 這就是為什么通常不鼓勵使用它,除非您有非常特殊的需求。

只有創建視圖層次結構的原始線程才能接觸其視圖。

當您嘗試從主線程外部修改視圖時會發生此錯誤,如果您從GlobalScope中啟動的協程中執行此操作會發生這種情況(因為它由單獨的線程池支持)。

在您的第二個片段中,您使用的是withContext(Dispatchers.Default) ,它只使這部分代碼在該線程池上運行,但 rest 在 UI 線程上運行。 這就是 UI 更新正常的原因。

請注意,Room 已經使用帶有后台線程池的調度程序進行查詢,因此您不需要像這樣手動切換上下文,您可以從 UI 線程中調用它。

旁注:像這樣使用MainScope().launch {.. }是個壞主意,因為它會遇到與GlobalScope相同的取消問題。 要正確使用它,您需要將此 scope 提取到變量/屬性中,以便在適當時取消它。 也就是說,使用現有的 scope 會更容易。 Android 已經在具有生命周期的活動等組件中提供了一個即用型協程 scope (請參閱lifecycle-runtime-ktx庫)。 它被稱為lifecycleScope 您應該在此 scope 中啟動您的協程,以便在銷毀活動時自動取消它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM