question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Android UI dispatcher and isDispatchNeeded

See original GitHub issue

Could we change implementation of method HandlerContext.isDispatchNeeded() to be more flexible:

public class HandlerContext(
    private val handler: Handler,
    private val name: String? = null,
    val alwaysDispatch: Boolean = true
) : CoroutineDispatcher(), Delay {

    override fun isDispatchNeeded(context: CoroutineContext): Boolean {
        return alwaysDispatch || Looper.myLooper() == handler.looper
    }

}

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:19 (10 by maintainers)

github_iconTop GitHub Comments

2reactions
qwwdfsadcommented, Jun 4, 2018

Instead of extending HandlerContext you can use delegation.

// You can name it UI or ConditionalUI or whatever
object ConditionalDispatcher : CoroutineDispatcher() {

    override fun dispatch(context: CoroutineContext, block: Runnable) = UI.dispatch(context, block)

    override fun isDispatchNeeded(context: CoroutineContext): Boolean {
        return Looper.myLooper() !== Looper.getMainLooper()
    }
}

Does it solve your problem?

1reaction
adampcommented, Jul 9, 2018

Regarding the original problem - getting dispatch behavior similar to LiveData where downstream behavior can interrupt or otherwise affect the rest of the dispatch - it sounds like you either want observers that need to affect the dispatch to use Unconfined or the wrapped dispatcher proposed above. However, using anything other than Unconfined here means that under some circumstances that might not be easily reproduced, your observer won’t be able to affect the upstream dispatch, but it might assume it can. That sounds like a recipe for bugs.

It also looks like skipping dispatch in the manner proposed here also breaks some ordering guarantees. Consider:

  1. Message A is posted to the Handler
  2. Message B is posted to the Handler
  3. Message A executes, performs some operation that results in processing and dispatch of Message C
  4. Message C skips dispatch and executes immediately since it’s on the main thread already
  5. Message B executes after Message C has executed

If message B and C were the result of dequeuing some sort of work from the same queue, they’re now out of order. This might happen many layers deep in the associated code and be very difficult to track.

A number of RxJava users in the Android community have written Schedulers that behave this way and got bit by ordering bugs like the above. The answer on that side of things has usually been either, “don’t use observeOn if you need it to run synchronously” (Unconfined) or to address the latency issues that come from the vsync barriers if that’s the motivation.

Read more comments on GitHub >

github_iconTop Results From Across the Web

isDispatchNeeded - Kotlin
E.g. MainCoroutineDispatcher.immediate checks whether we are already in the required UI thread in this method and avoids an additional dispatch when it is ......
Read more >
AndroidUiDispatcher - Android Developers
Use Main to obtain a dispatcher for the process's main thread (i.e. the activity thread) or CurrentThread to ... isDispatchNeeded(context: CoroutineContext).
Read more >
Kotlin coroutine unit test fails with "Module with the Main ...
This is thrown because Dispatcher.Main is missing. It is Android based and therefore cannot be used for unit tests. The solution lies in...
Read more >
Kotlin coroutines: Dispatchers.Main context for RoboVM applications ...
Android has kotlinx-coroutines-android Dispatcher.Main that coroutine execution on main/ui thread. It allows writing an effective suspend logic on main ...
Read more >
Guide to UI programming with coroutines
Also, UI dispatcher is available via Dispatchers.Main from kotlinx-coroutines-core and corresponding implementation (Android, JavaFx or Swing) is discovered ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found