@@ -25,16 +25,41 @@ private const val MAX_DELAY = Long.MAX_VALUE / 2 // cannot delay for too long on
25
25
26
26
/* *
27
27
* Implements [CoroutineDispatcher] on top of an arbitrary Android [Handler].
28
- * @param handler a handler.
29
- * @param name an optional name for debugging.
30
28
*/
31
- public class HandlerContext (
29
+ public class HandlerContext private constructor (
32
30
private val handler : Handler ,
33
- private val name : String? = null
31
+ private val name : String? ,
32
+ private val invokeImmediately : Boolean
34
33
) : 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
+
35
56
@Volatile
36
57
private var _choreographer : Choreographer ? = null
37
58
59
+ override fun isDispatchNeeded (context : CoroutineContext ): Boolean {
60
+ return ! invokeImmediately || Looper .myLooper() != handler.looper
61
+ }
62
+
38
63
override fun dispatch (context : CoroutineContext , block : Runnable ) {
39
64
handler.post(block)
40
65
}
0 commit comments