16
16
17
17
package kotlinx.coroutines.experimental.android
18
18
19
- import android.os.Handler
20
- import android.os.Looper
21
- import android.view.Choreographer
19
+ import android.os.*
20
+ import android.view.*
22
21
import kotlinx.coroutines.experimental.*
23
- import java.util.concurrent.TimeUnit
24
- import kotlin.coroutines.experimental.CoroutineContext
22
+ import java.util.concurrent.*
23
+ import kotlin.coroutines.experimental.*
25
24
26
25
/* *
27
26
* Dispatches execution onto Android main UI thread and provides native [delay][Delay.delay] support.
@@ -37,16 +36,41 @@ private const val MAX_DELAY = Long.MAX_VALUE / 2 // cannot delay for too long on
37
36
38
37
/* *
39
38
* Implements [CoroutineDispatcher] on top of an arbitrary Android [Handler].
40
- * @param handler a handler.
41
- * @param name an optional name for debugging.
42
39
*/
43
- public class HandlerContext (
40
+ public class HandlerContext private constructor (
44
41
private val handler : Handler ,
45
- private val name : String? = null
42
+ private val name : String? ,
43
+ private val invokeImmediately : Boolean
46
44
) : CoroutineDispatcher(), Delay {
45
+ /* *
46
+ * Creates [CoroutineDispatcher] for the given Android [handler].
47
+ *
48
+ * @param handler a handler.
49
+ * @param name an optional name for debugging.
50
+ */
51
+ public constructor (
52
+ handler: Handler ,
53
+ name: String? = null
54
+ ) : this (handler, name, false )
55
+
56
+ @Volatile
57
+ private var _immediate : HandlerContext ? = if (invokeImmediately) this else null
58
+
59
+ /* *
60
+ * Returns dispatcher that executes coroutines immediately when it is already in the right handler context
61
+ * (current looper is the same as [handler] looper). See [isDispatchNeeded] documentation on
62
+ * why this should not be done by default.
63
+ */
64
+ public val immediate: HandlerContext = _immediate ? :
65
+ HandlerContext (handler, name, true ).also { _immediate = it }
66
+
47
67
@Volatile
48
68
private var _choreographer : Choreographer ? = null
49
69
70
+ override fun isDispatchNeeded (context : CoroutineContext ): Boolean {
71
+ return ! invokeImmediately || Looper .myLooper() != handler.looper
72
+ }
73
+
50
74
override fun dispatch (context : CoroutineContext , block : Runnable ) {
51
75
handler.post(block)
52
76
}
0 commit comments