Lisa Anne
Lisa Anne

Reputation: 4595

Kotlin coroutines: why is this not throwing a NetworkOnMainThreadException?

client uses Retrofit Coroutines Adapter.

I don't understand, why am I not getting NetworkOnMainThreadException?? Is't it called on the main thread??

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val deferred = client.getStuffDeferred(file)
    CoroutineScope(Dispatchers.Main).launch {
        val response = deferred.await()
    }
}

Upvotes: 3

Views: 2292

Answers (2)

Ramzy Hassan
Ramzy Hassan

Reputation: 966

if you call launch on the Dispatchers.Main it does run on the main thread but suspends the execution so as to not block the thread.

So That this behavior does not block or throw NetworkOnMainThreadException because there is not suspending methods or runBlocking method in your CoroutineScope

But: you should change your context during making a network operation or any heavy operation with may slow down your UI thread operation by using

withContext(Dispatchers.IO){// your suspended calls}

which allows you to change your current context to the background thread and continue your work in the main thread without any problem

Take a look into this article on solution3 which use Coroutine

Upvotes: 0

Jeel Vankhede
Jeel Vankhede

Reputation: 12118

If you pass Coroutine Context to your coroutine builder, then such coroutine will use that thread to execution.

I.e.

  1. Dispatchers.Default – is used by all standard builder if no dispatcher nor any other ContinuationInterceptor is specified in their context. It uses a common pool of shared background threads. This is an appropriate choice for compute-intensive coroutines that consume CPU resources.
  2. Dispatchers.IO – uses a shared pool of on-demand created threads and is designed for offloading of IO-intensive blocking operations (like file I/O and blocking socket I/O).
  3. Dispatchers.Unconfined – starts coroutine execution in the current call-frame until the first suspension. On first suspension the coroutine builder function returns. The coroutine resumes in whatever thread that is used by the corresponding suspending function, without confining it to any specific thread or pool. Unconfined dispatcher should not be normally used in code.
  4. Private thread pools can be created with newSingleThreadContext and newFixedThreadPoolContext.
  5. An arbitrary Executor can be converted to dispatcher with asCoroutineDispatcher extension function.

So, use like :

CoroutineScope(Dispatchers.IO).launch { // we should use IO thread here !

}

Upvotes: 2

Related Questions