isDispatchNeeded
fun isDispatchNeeded(context: CoroutineContext): Boolean
(source)Overrides CoroutineDispatcher.isDispatchNeeded
Returns true
if execution shall be dispatched onto another thread.
The default behaviour for most dispatchers is to return true
.
UI dispatchers should not override isDispatchNeeded
, but leave a default implementation that
returns true
. To understand the rationale beyond this recommendation, consider the following code:
fun asyncUpdateUI() = async(MainThread) {
// do something here that updates something in UI
}
When you invoke asyncUpdateUI
in some background thread, it immediately continues to the next
line, while UI update happens asynchronously in the UI thread. However, if you invoke
it in the UI thread itself, it updates UI synchronously if your isDispatchNeeded
is
overridden with a thread check. Checking if we are already in the UI thread seems more
efficient (and it might indeed save a few CPU cycles), but this subtle and context-sensitive
difference in behavior makes the resulting async code harder to debug.
Basically, the choice here is between “JS-style” asynchronous approach (async actions
are always postponed to be executed later in the even dispatch thread) and “C#-style” approach
(async actions are executed in the invoker thread until the first suspension point).
While, C# approach seems to be more efficient, it ends up with recommendations like
“use yield
if you need to ….”. This is error-prone. JS-style approach is more consistent
and does not require programmers to think about whether they need to yield or not.
However, coroutine builders like launch and async accept an optional CoroutineStart parameter that allows one to optionally choose C#-style CoroutineStart.UNDISPATCHED behaviour whenever it is needed for efficiency.