ursus
09/28/2021, 2:07 AMclass Foo {
private val scope = CoroutineScope(SupervisedJob() + Dispatchers.Main.immediate)
fun init() {
println("a")
scope.launch {
println("b")
flowOf("hello")
.collect {
println("c")
}
}
println("d")
}
}
I'm pretty sure this emmited printed a, b, c, d
in the past when using immediate main dispatcher on android
but now it emits a, d, b, c
Is there a way to make this blocking as it was in rxjava?
I thought this exactly was the difference between Dispatchers.Main
and Dispatchers.Main.immediate
ephemient
09/28/2021, 2:28 AMDispatchers.main
and Dispatchers.Main.immediate
is
withContext(Dispatchers.Main) {
println("a") // may be in next event loop
}
withContext(DIspatchers.Main.immediate) {
println("b") // in the same event loop, if current thread is main UI thread
}
but I don't think it is meant to guarantee anything about launch()
ursus
09/28/2021, 2:36 AMlouiscad
09/28/2021, 6:07 AMuli
09/28/2021, 6:21 AMReturns dispatcher that executes coroutines immediately
I’d also say launch
creates a coroutine that should therefor be executed immediately. So I’d at least. expect b
before d
. I don’t think there are any guarantees about c
though.bezrukov
09/28/2021, 7:34 AMa, d, b, c
is expected if it's called from non-main dispatcherursus
09/28/2021, 11:36 AMuli
09/28/2021, 1:37 PM2021-09-28 15:36:20.409 27971-27971/I/System.out: Coroutines: a
2021-09-28 15:36:20.413 27971-27971/I/System.out: Coroutines: b
2021-09-28 15:36:20.414 27971-27971/I/System.out: Coroutines: c
2021-09-28 15:36:20.414 27971-27971/I/System.out: Coroutines: d
That’s Kotlin 1.5.31 on Android with Coroutines 1.5.2println("${Thread.currentThread()}: a")
and so ond
scope.launch {
sleep(1)
println("b")
ursus
09/28/2021, 6:20 PMclass Activity {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
fun onCreate() {
scope.launch {
val uri = fetchUri()
if (uri != null) {
val viewModel = FooViewModel(..)
viewModel.init()
}
}
}
}
class FooViewModel {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
fun init() {
Log.d("Default", "a")
scope.launch {
Log.d("Default", "b")
flowOf("hello")
.collect {
Log.d("Default", "c")
}
}
Log.d("Default", "d")
}
}
If I dont fetch the uri via coroutines (use callbacks; basically not using the outer scope.launch), it works correctly 🤷♂️🤷♂️
So the issue is nesting the 2 main thread coroutine scopes .. not sure why
Which is a rather big problem, since I do this all over (Activity subscribing to some "global" streams like flow of User instances, and when null
is emitted, it should reset backstack to login screen (which has its viewmodel etc, the same situation as above)uli
09/28/2021, 8:36 PMclass MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
scope.launch {
fetchUri()
init()
}
}
suspend fun fetchUri() = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
delay(100)
}
private fun init() {
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
println("Coroutines: ${Thread.currentThread()}: a")
scope.launch {
println("Coroutines: ${Thread.currentThread()}: b")
flowOf("hello")
.collect {
println("Coroutines: ${Thread.currentThread()}: c")
}
}
println("Coroutines: ${Thread.currentThread()}: d")
}
}
2021-09-28 22:30:56.895 16765-16765/I/System.out: Coroutines: Thread[main,5,main]: a
2021-09-28 22:30:56.897 16765-16765/I/System.out: Coroutines: Thread[main,5,main]: b
2021-09-28 22:30:56.905 16765-16765/I/System.out: Coroutines: Thread[main,5,main]: c
2021-09-28 22:30:56.906 16765-16765/I/System.out: Coroutines: Thread[main,5,main]: d
ursus
09/28/2021, 8:53 PMuli
09/28/2021, 8:56 PMursus
09/28/2021, 8:59 PMuli
09/28/2021, 9:14 PMursus
09/28/2021, 9:14 PMuli
09/28/2021, 9:15 PMursus
09/28/2021, 9:50 PMclass Activity {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
fun onCreate() {
scope.launch {
delay(1000)
val viewModel = FooViewModel(..)
viewModel.init()
}
}
}
then it fixes it self, is that a clue?bezrukov
09/28/2021, 9:50 PMuli
09/28/2021, 9:53 PMfetchUri()
(i.e. delay) it behaves wired here as wellursus
09/28/2021, 9:57 PMuli
09/28/2021, 10:11 PMursus
09/28/2021, 10:12 PMuli
09/28/2021, 10:13 PMephemient
09/28/2021, 10:14 PMlaunch(start = UNDISPATCHED)
as I mentioned way backursus
09/28/2021, 10:15 PMuli
09/28/2021, 10:21 PMursus
09/28/2021, 10:22 PMephemient
09/28/2021, 10:22 PMlaunch()
to start without dispatching was never a safe assumption even if it happened to workuli
09/28/2021, 10:23 PMursus
09/28/2021, 10:25 PMdrop(1)
and trigger the work again; now since the collection is dispatched, and I trigger work sooner, I miss a state emit, which is baduli
09/28/2021, 10:25 PMursus
09/28/2021, 10:30 PMuli
09/28/2021, 10:31 PMursus
09/28/2021, 10:34 PMuli
09/28/2021, 10:35 PMursus
09/28/2021, 10:35 PMuli
09/28/2021, 10:54 PMephemient
09/29/2021, 2:43 AMuli
09/29/2021, 6:35 AMursus
09/29/2021, 6:52 PM