Skip to content

Commit ef548b3

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

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/main/kotlin/kotlinx/coroutines/experimental/android/HandlerContext.kt

+33-9
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616

1717
package kotlinx.coroutines.experimental.android
1818

19-
import android.os.Handler
20-
import android.os.Looper
21-
import android.view.Choreographer
19+
import android.os.*
20+
import android.view.*
2221
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.*
2524

2625
/**
2726
* 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
3736

3837
/**
3938
* Implements [CoroutineDispatcher] on top of an arbitrary Android [Handler].
40-
* @param handler a handler.
41-
* @param name an optional name for debugging.
4239
*/
43-
public class HandlerContext(
40+
public class HandlerContext private constructor(
4441
private val handler: Handler,
45-
private val name: String? = null
42+
private val name: String?,
43+
private val invokeImmediately: Boolean
4644
) : 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+
4767
@Volatile
4868
private var _choreographer: Choreographer? = null
4969

70+
override fun isDispatchNeeded(context: CoroutineContext): Boolean {
71+
return !invokeImmediately || Looper.myLooper() != handler.looper
72+
}
73+
5074
override fun dispatch(context: CoroutineContext, block: Runnable) {
5175
handler.post(block)
5276
}

0 commit comments

Comments
 (0)