article link: kotlin-coroutines
Dispatchers: Dispatchers help coroutines in deciding the thread on which the work has to be done. There are majorly three types of Dispatchers which are IO, Default, and Main. Dispatchers 是帮助协程决定在哪一个线程上执行任务, 主要有三种: IO, Default 和 Main
- IO: is used for doing the network and disk-related work (适合 网络请求 和 文件操作)
- Default: is used to do the CPU-intensive work (适合 密集型的 任务处理 )
- Main: is the UI thread of Android, default (UI渲染)
Dispatchers.Default
We should use Dispatchers.Default
to perform CPU-intensive tasks.
Example use cases:
- Doing heavy calculations like Matrix multiplications.
- Doing any operations on a bigger list presentin the memory like sorting, filtering, searching, etc.
- Applying the filter on the Bitmap present in the memory, NOT by reading the image file present on the disk.
- Parsing the JSON available in the memory, NOT by reading the JSON file present on the disk.
- Scaling the bitmap already present in the memory, NOT by reading the image file present on the disk.
- Any operations on the bitmap that are already present in the memory, NOT by reading the image file present on the disk.
Dispatchers.IO
We should use Dispatchers.IO
to perform disk or network I/O-related tasks.
Example use cases:
- Any network operations like making a network call.
- Downloading a file from the server.
- file/database operate
- Moving a file from one location to another on disk.
- Reading from a file.
- Writing to a file.
- Making a database query.
- Loading the Shared Preferences.
Dispatchers.Main
We should use Dispatchers.Main
to run a coroutine on the main thread of Android. We all know where we use the main thread of Android. Mainly at the places where we interact with the UI and perform small tasks.
Example use cases:
- Performing UI-related tasks.
- Any small tasks like any operations on a smaller list present in the memory like sorting, filtering, searching, etc.
Dispatchers.Unconfined
It does not change the thread. When it is started, it runs on the thread on which it was started. If it is resumed, it runs on the thread that resumed it.
- suspend: Suspend function is a function that could be started, paused, and resume.
The difference is that the launch{}
returns a Job
and does not carry any resulting value whereas the async{}
returns an instance of Deferred<T>
, which has an await()
function that returns the result of the coroutine like we have future in Java in which we do future.get()
to get the result.
withContext
does not create a new coroutine, it only shifts the context of the existing coroutine and it's a suspend function whereas launch
and async
create a new coroutine and they are not suspend functions.
The thumb-rules:
- Both the
launch
andasync
are used to launch a coroutine. This enables us to do tasks in parallel. async
can be used to get the result that is not possible with thelaunch
.withContext
does not launch a coroutine and it is just asuspend
function used for shifting the context of the existing coroutine.
Scope:
- GlobalScope
- lifyCycleScope
- viewModelScope
This is how supervisorScope
helps.
Conclusion:
-
While NOT using
async
, we can go ahead with thetry-catch
or theCoroutineExceptionHandler
and achieve anything based on our use cases. -
While using
async
, in addition totry-catch
, we have two options:coroutineScope
andsupervisorScope
. -
With
async
, usesupervisorScope
with the individualtry-catch
for each task, when you want to continue with other tasks if one or some of them have failed. -
With
async
, usecoroutineScope
with the top-leveltry-catch
, when you do NOT want to continue with other tasks if any of them have failed.