Coroutines – Dispatcher & Yield

Today another day in quarantine since the COVID-19 outbreak. So I thought let’s really learn how coroutines work instead of just using it and hope for the best. I did the codelab from Google that did a pretty good job for me to understand how it works.

I wanted to highlight how to dispatch a coroutine and how it could be shorter then you think.

To switch between any dispatcher, coroutines uses withContext. Calling withContext switches to the other dispatcher just for the lambda then comes back to the dispatcher that called it with the result of that lambda.

By default, Kotlin coroutines provides three Dispatchers: MainIO, and Default. The IO dispatcher is optimized for IO work like reading from the network or disk, while the Default dispatcher is optimized for CPU intensive tasks.

This code doesn’t support coroutine cancellation, but it can! Coroutine cancellation is cooperative. That means your code needs to check for cancellation explicitly, which happens for you whenever you call the functions in kotlinx-coroutines.

Because this withContext block only calls blocking calls it will not be cancelled until it returns from withContext.

To fix this, you can call yield regularly to give other coroutines a chance run and check for cancellation. Here you would add a call to yield between the network request and the database query. Then, if the coroutine is cancelled during the network request, it won’t save the result to the database.

You can also check cancellation explicitly, which you should do when making low-level coroutine interfaces.

Both Room and Retrofit use a custom dispatcher and do not use Dispatchers.IO. Room will run coroutines using the default query and transaction Executor that’s configured. Retrofit will create a new Call object under the hood, and call enqueue on it to send the request asynchronously.

You do not need to use withContext to call main-safe suspending functions. Since both Room and Retrofit provide main-safe suspending functions, it’s safe to orchestrate this async work from Dispatchers.Main.

By convention, you should ensure that suspend functions written in your application are main-safe. That way it is safe to call them from any dispatcher, even Dispatchers.Main.

Add a Comment

Your email address will not be published. Required fields are marked *