Skip to content
This repository was archived by the owner on Apr 18, 2021. It is now read-only.

Commit 4978417

Browse files
committed
1. Fix issue #4, won't dispatch any coroutines with EmptyScope.
1 parent 5cb7235 commit 4978417

File tree

4 files changed

+47
-3
lines changed

4 files changed

+47
-3
lines changed

MainScope/src/main/java/com/bennyhuo/kotlin/coroutines/android/mainscope/MainScope.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.app.Application
44
import com.bennyhuo.kotlin.coroutines.android.mainscope.internal.ActivityLifecycleCallbackImpl
55
import com.bennyhuo.kotlin.coroutines.android.mainscope.job.EmptyInterceptor
66
import com.bennyhuo.kotlin.coroutines.android.mainscope.job.EmptyJob
7+
import com.bennyhuo.kotlin.coroutines.android.mainscope.job.ImmutableCoroutineContext
78
import kotlinx.coroutines.CoroutineScope
89
import kotlinx.coroutines.Dispatchers
910
import kotlinx.coroutines.SupervisorJob
@@ -25,5 +26,5 @@ internal class MainScopeImpl: MainScope {
2526
}
2627

2728
internal object EmptyScope : MainScope {
28-
override val coroutineContext: CoroutineContext = EmptyJob() + EmptyInterceptor
29+
override val coroutineContext: CoroutineContext = ImmutableCoroutineContext(EmptyJob() + EmptyInterceptor)
2930
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.bennyhuo.kotlin.coroutines.android.mainscope.job
2+
3+
import kotlin.coroutines.CoroutineContext
4+
import kotlin.coroutines.CoroutineContext.Element
5+
import kotlin.coroutines.CoroutineContext.Key
6+
7+
class ImmutableCoroutineContext(private val coroutineContext: CoroutineContext): CoroutineContext {
8+
override fun <R> fold(initial: R, operation: (R, Element) -> R): R = coroutineContext.fold(initial, operation)
9+
10+
override fun <E : Element> get(key: Key<E>) = coroutineContext[key]
11+
12+
override fun minusKey(key: Key<*>) = this
13+
14+
override fun plus(context: CoroutineContext) = this
15+
}

MainScope/src/main/java/com/bennyhuo/kotlin/coroutines/android/mainscope/job/JobCompat.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ abstract class JobCompat implements Job {
1111
@NotNull
1212
@Override
1313
public final ChildHandle attachChild(@NotNull ChildJob childJob) {
14+
//Parent is already cancelled. So cancel child directly.
15+
childJob.cancel(getCancellationException());
1416
return EmptyChildHandle.instance;
1517
}
1618

app/src/main/java/com/bennyhuo/kotlin/coroutines/android/sample/MainActivity.kt

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import com.bennyhuo.kotlin.coroutines.android.mainscope.RecyclerViewScoped
1212
import com.bennyhuo.kotlin.coroutines.android.mainscope.internal.withMainScope
1313
import kotlinx.android.synthetic.main.activity_main.*
1414
import kotlinx.coroutines.*
15+
import kotlinx.coroutines.CoroutineStart.ATOMIC
16+
import kotlinx.coroutines.CoroutineStart.UNDISPATCHED
1517

1618
class MainActivity : AppCompatActivity(), AppCompatScoped, RecyclerViewScoped, DesignScoped {
1719

@@ -67,10 +69,34 @@ class MainActivity : AppCompatActivity(), AppCompatScoped, RecyclerViewScoped, D
6769
withMainScope {
6870
launch {
6971
val job = coroutineContext[Job]
70-
log("This may be dispatched according to the start mode. isActive: ${job?.isActive}, isCancelled: ${job?.isCancelled}")
72+
log("This may be dispatched according to the start mode: DEFAULT. isActive: ${job?.isActive}, isCancelled: ${job?.isCancelled}")
7173
//Scope is cancelled, so any cancellable suspend functions will respond to it.
7274
delay(100)
73-
log("Never gonna happen.")
75+
log("[DEFAULT][Empty]Never gonna happen.")
76+
}
77+
78+
launch(start = ATOMIC) {
79+
val job = coroutineContext[Job]
80+
log("This may be dispatched according to the start mode: ATOMIC. isActive: ${job?.isActive}, isCancelled: ${job?.isCancelled}")
81+
//Scope is cancelled, so any cancellable suspend functions will respond to it.
82+
delay(100)
83+
log("[ATOMIC][DEFAULT]Never gonna happen.")
84+
}
85+
86+
launch(start = UNDISPATCHED) {
87+
val job = coroutineContext[Job]
88+
log("This may be dispatched according to the start mode: UNDISPATCHED. isActive: ${job?.isActive}, isCancelled: ${job?.isCancelled}")
89+
//Scope is cancelled, so any cancellable suspend functions will respond to it.
90+
delay(100)
91+
log("[UNDISPATCHED][DEFAULT]Never gonna happen.")
92+
}
93+
94+
launch(Dispatchers.Default) {
95+
val job = coroutineContext[Job]
96+
log("This may be dispatched according to the start mode: DEFAULT, using Dispatcher: Default. isActive: ${job?.isActive}, isCancelled: ${job?.isCancelled}")
97+
//Scope is cancelled, so any cancellable suspend functions will respond to it.
98+
delay(100)
99+
log("[DEFAULT][DEFAULT]Never gonna happen.")
74100
}
75101
}
76102
}

0 commit comments

Comments
 (0)