@@ -25,16 +25,41 @@ private const val MAX_DELAY = Long.MAX_VALUE / 2 // cannot delay for too long on
2525
2626/* *
2727 * Implements [CoroutineDispatcher] on top of an arbitrary Android [Handler].
28- * @param handler a handler.
29- * @param name an optional name for debugging.
3028 */
31- public class HandlerContext (
29+ public class HandlerContext private constructor (
3230 private val handler : Handler ,
33- private val name : String? = null
31+ private val name : String? ,
32+ private val invokeImmediately : Boolean
3433) : CoroutineDispatcher(), Delay {
34+ /* *
35+ * Creates [CoroutineDispatcher] for the given Android [handler].
36+ *
37+ * @param handler a handler.
38+ * @param name an optional name for debugging.
39+ */
40+ public constructor (
41+ handler: Handler ,
42+ name: String? = null
43+ ) : this (handler, name, false )
44+
45+ @Volatile
46+ private var _immediate : HandlerContext ? = if (invokeImmediately) this else null
47+
48+ /* *
49+ * Returns dispatcher that executes coroutines immediately when it is already in the right handler context
50+ * (current looper is the same as [handler] looper). See [isDispatchNeeded] documentation on
51+ * why this should not be done by default.
52+ */
53+ public val immediate: HandlerContext = _immediate ? :
54+ HandlerContext (handler, name, true ).also { _immediate = it }
55+
3556 @Volatile
3657 private var _choreographer : Choreographer ? = null
3758
59+ override fun isDispatchNeeded (context : CoroutineContext ): Boolean {
60+ return ! invokeImmediately || Looper .myLooper() != handler.looper
61+ }
62+
3863 override fun dispatch (context : CoroutineContext , block : Runnable ) {
3964 handler.post(block)
4065 }
0 commit comments