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