Skip to content

Commit 0e4e8ec

Browse files
committed
Provide HandlerContext.immediate extension to immediately execute tasks which are invoked from the right context
Fixes #381
1 parent f9408f6 commit 0e4e8ec

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
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

+22-6
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.
@@ -32,9 +31,26 @@ public class HandlerContext(
3231
private val handler: Handler,
3332
private val name: String? = null
3433
) : CoroutineDispatcher(), Delay {
34+
35+
/**
36+
* Dispatcher which executes given block immediately if [isDispatchNeeded] is already in the right handler context
37+
* (current looper is the same as [handler] looper). If not, block is dispatched regularly via [handler]
38+
*/
39+
public val immediate: HandlerContext by lazy { HandlerContext(handler, name, true) }
40+
41+
private var invokeImmediately: Boolean = false
42+
43+
private constructor(handler: Handler, name: String?, invokeImmediately: Boolean) : this(handler, name) {
44+
this.invokeImmediately = invokeImmediately
45+
}
46+
3547
@Volatile
3648
private var _choreographer: Choreographer? = null
3749

50+
override fun isDispatchNeeded(context: CoroutineContext): Boolean {
51+
return !invokeImmediately || Looper.myLooper() != handler.looper
52+
}
53+
3854
override fun dispatch(context: CoroutineContext, block: Runnable) {
3955
handler.post(block)
4056
}
@@ -68,7 +84,7 @@ public class HandlerContext(
6884
// post into looper thread thread to figure it out
6985
return suspendCancellableCoroutine { cont ->
7086
handler.post {
71-
updateChoreographerAndPostFrameCallback(cont)
87+
updateChoreographerAndPostFrameCallback(cont)
7288
}
7389
}
7490
}

0 commit comments

Comments
 (0)