Skip to content

Commit 16db755

Browse files
qwwdfsadelizarov
authored andcommitted
Provide HandlerContext.immediate extension to immediately execute tasks which are invoked from the right context
Fixes #381
1 parent fb4a332 commit 16db755

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

binary-compatibility-validator/reference-public-api/kotlinx-coroutines-android.txt

+2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ public final class kotlinx/coroutines/experimental/android/HandlerContext : kotl
1010
public fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
1111
public fun dispatch (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Runnable;)V
1212
public fun equals (Ljava/lang/Object;)Z
13+
public final fun getImmediate ()Lkotlinx/coroutines/experimental/android/HandlerContext;
1314
public fun hashCode ()I
1415
public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
16+
public fun isDispatchNeeded (Lkotlin/coroutines/experimental/CoroutineContext;)Z
1517
public fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
1618
public fun toString ()Ljava/lang/String;
1719
}

ui/kotlinx-coroutines-android/src/HandlerContext.kt

+33-9
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
package kotlinx.coroutines.experimental.android
66

7-
import android.os.Handler
8-
import android.os.Looper
9-
import android.view.Choreographer
7+
import android.os.*
8+
import android.view.*
109
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.*
1312

1413
/**
1514
* 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
2524

2625
/**
2726
* Implements [CoroutineDispatcher] on top of an arbitrary Android [Handler].
28-
* @param handler a handler.
29-
* @param name an optional name for debugging.
3027
*/
31-
public class HandlerContext(
28+
public class HandlerContext private constructor(
3229
private val handler: Handler,
33-
private val name: String? = null
30+
private val name: String?,
31+
private val invokeImmediately: Boolean
3432
) : 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+
3555
@Volatile
3656
private var _choreographer: Choreographer? = null
3757

58+
override fun isDispatchNeeded(context: CoroutineContext): Boolean {
59+
return !invokeImmediately || Looper.myLooper() != handler.looper
60+
}
61+
3862
override fun dispatch(context: CoroutineContext, block: Runnable) {
3963
handler.post(block)
4064
}

0 commit comments

Comments
 (0)