Is there a way to circumvent stuff like? ```scope....
# decompose
b
Is there a way to circumvent stuff like?
Copy code
scope.launch(Dispatchers.Main.immediate) {
    navigation.replaceCurrent(...)
}
We do that do prevent runtime exceptions due to wrong coroutine context by some caller of a public API... is there a reason, why decompose enforces the main dispatcher?
a
The primary reason is because it's much less error-prone, when you don't mess with threading. It's often better to receive an immediate crash at runtime rather than having random flaky issues due to race conditions. Another reason is because the navigation is performed synchronously. You definitely don't want to switch components and their lifecycles on random threads. For the same reason LiveData enforces the main thread by default (there is a separate method for asynchronous updates though). The fact that you have to
launch
just to navigate suggests that something is not good with data flows in your projects. Usually you navigate in response to UI events (those are already on the main thread). Or you observe some events - in this case you should explicitly specify the Main dispatcher (or
observeOn(mainScheduler)
with Rx). E.g.
Copy code
mainScope.launch {
    events.collect {
        // Navigate here
    }
}
b
I have taken a closer look at our code and have now switched to the following:
Copy code
suspend fun <C : Any> StackNavigator<C>.popSuspending(
    onComplete: (isSuccess: Boolean) -> Unit = {}
) = withContext(Dispatchers.Main.immediate) {
    pop(onComplete)
}
Could it make sense to add this to decompose? We don't want to force users of our API to have knowledge about decompose. They just should call for example
fun okButtonPressend()
without to worry, if they call it from within a coroutine and switch context or not. The implementation on our side currently would be
fun okButtonPressed() = scopeWithLifecycle.launch { popSuspsending() }
.
a
Thanks for the update.
Could it make sense to add this to decompose?
I'm afraid no. But you can add those as extensions specifically for your project.
We don't want to force users of our API to have knowledge about decompose.
This is a good decision. I agree.
They just should call for example
fun okButtonPressend()
without to worry
But this is something I would think twice about. 1.
onBackButtonPressed
name means that the back button was pressed. Usually back buttons are pressed on the main thread. If the client calls this methods from another thread, either they are abusing the API or the method should be renamed (e.g.
goBack
). 2. You can still force your users to use the correct thread without telling them you are using Decompose. The same story with Android Views, Swing and many other UI frameworks. You are required to update the UI on the UI thread. As a developer and a user of that API, it's your responsibility. Delegating thread switching to the UI framework is very error-prone and may lead to hard-to-debug race conditions in client's application. So, if you really believe this is the good way for your API, then please add extensions with thread switching specifically for your project.