Home > database >  MainScope vs GlobalScope
MainScope vs GlobalScope

Time:12-03

What is the difference between GlobalScope and MainScope?

//Accessing data from Room
GlobalScope.launch {
            v.tvStoreName.text = pfViewModel.getStoreName()
            pageDetails.pageNumber = currentPage
            pageDetails.pageSize = pageSize
            pfViewModel.getTransactions(pageDetails, toolbarBuilder?.getDate()!!)
        }

The GlobalScope sometimes makes an error which is very hard to reproduce.

Fatal Exception: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

MainScope().launch {
            var storeName = ""
            withContext(Dispatchers.Default) {
                storeName = pfViewModel.getStoreName()
            }
            v.tvStoreName.text = storeName
        }

CodePudding user response:

What is the difference between GlobalScope and MainScope?

MainScope is a CoroutineScope that uses the Dispatchers.Main dispatcher by default, which is bound to the main UI thread.

The GlobalScope is a CoroutineScope that has no dispatcher in its coroutine context. This means that the coroutines launched in this scope will use the Dispatchers.Default dispatcher, which is backed by a thread pool (sized based on the number of CPU cores you have).

The GlobalScope also has no Job in its context, which means structured concurrency doesn't apply. Coroutines launched in it are never cancelled automatically, so they need to be manually controlled. This is why it is usually discouraged to use it unless you have very specific needs.

Only the original thread that created a view hierarchy can touch its views.

This error occurs when you're trying to modify views from outside the main thread, which is what happens if you do this from coroutines launched in the GlobalScope (because it's backed by a separate thread pool).

In your second snippet, you are using withContext(Dispatchers.Default), which only makes this part of the code run on that thread pool, but the rest runs on UI thread. This is why the update of the UI is ok there.

Note that Room already uses a dispatcher with a background thread pool for its queries, so you don't need to switch context manually like this, you can just call it from the UI thread.

Side note: using MainScope().launch { .. } like this is a bad idea, because it suffers from the same cancellation issue as GlobalScope. To use it properly, you would need to extract this scope into a variable/property so you can cancel it when appropriate. That said, it's easier to use an existing scope. Android already provides a ready-to-use coroutine scope in components such as Activities which have a lifecycle (see lifecycle-runtime-ktx library). It's called lifecycleScope. You should launch your coroutines in this scope so they automatically get cancelled when the activity is destroyed.

  • Related