why can’t we have @Composable function with suspen...
# compose
v
why can’t we have @Composable function with suspension?
Copy code
content: @Composable suspend () -> Unit
s
I'm not sure exactly why the restriction exists, but you can use
rememberCoroutineScope
to be able to call suspend functions. Or use `LaunchedEffect`s
r
Someone with better knowledge may provide a better context and a more accurate answer, but composables are supposed to be fast to execute; whereas any suspend function is immediately ground for making it take its dear time. As such, if you allow suspendable composables, you then immediately lose any rough assurances that someone, somewhere in the hierarchy, won't put some composable that takes half a second to complete. How do you render a column with two composables, where the first one takes half a second to complete, without blocking both the column and its entire parent branch?
b
Jetpack Compose does not support
@Composable
functions being
suspend
functions directly for a few reasons. Here's an explanation of the key reasons: 1. Composable Function Execution Model Composable functions are designed to be declarative and to describe the UI. They can be recomposed multiple times by the Compose runtime, which controls their execution. Suspending functions, on the other hand, are part of Kotlin's coroutines framework, designed to handle asynchronous tasks that may involve waiting without blocking a thread. If a
@Composable
function were
suspend
, it would mix these two paradigms, complicating the Compose runtime's ability to manage and optimize UI recompositions. 2. Recomposition Handling The Compose runtime can recompose composable functions frequently to reflect changes in the state. These recompositions need to be fast and efficient. Suspending functions, which can pause execution, would introduce uncertainty about when and how long a composable might pause, disrupting the predictable flow of recomposition. 3. Separation of Concerns Composable functions are meant to describe what the UI should look like, while suspending functions describe asynchronous work. Mixing these two responsibilities can lead to code that's harder to reason about and maintain. Keeping these concerns separate allows for cleaner, more maintainable code. 4. Existing Patterns for Handling Asynchronous Work Compose provides specific patterns and functions to handle asynchronous work within composable functions, such as
LaunchedEffect
,
produceState
, and
rememberCoroutineScope
. These functions allow you to perform asynchronous work in a way that's compatible with the Compose runtime. TLDR While it might seem convenient to directly use suspending functions in
@Composable
functions, the separation of the UI description from asynchronous logic allows Compose to remain efficient and predictable. The provided side-effect handling APIs (
LaunchedEffect
,
produceState
, etc.) ensure that you can perform asynchronous work in a manner that's consistent with the Compose model.
v
I’m trying to use compose runtime for Non-UI purpose and would like composable function to return a value. Like this,
Copy code
@Composable suspend () -> Any
s
Why would you use a Composable function for a non UI purpose? That is the whole point of Composable functions. If it's to call it from a composable function you should either call a viewmodel function and get the result using a StateFlow or use rememberCoroutineScope.launch { } and update a remembered value or something like that
r
You can check into https://github.com/cashapp/molecule for how to use the Compose runtime for non-UI purposes. You would define a presenter composable function, which collects multiple flows as state, and then recomposes (and returns the result value) on every change of any state that was read in the composition. The flows themselves can use suspend operators to emit elements, so this would fit your use cases.
v
Since compose runtime can handle any tree like structure, I try experimenting for Non-UI purpose. I chose compose-runtime for these two features, • State machine • Invalidations also suggest me if you know any library, that can do both, I have explored molecule and It looks like one shot request. I am looking for something that can run parallel with existing Android Compose UI.
z
I’m not sure what you mean by “one shot request” but molecule is designed to generate model objects instead of emitting ui, continuously over the lifetime of an app or test, not just one shot
2
Compose functions can’t suspend because it’s extremely unclear what that would mean. There are tons of implications which don’t really make sense given what suspending means and how compose works, as mentioned above. A composable function’s main purpose is to declaratively emit some node or tree of nodes based on parameters and state objects, then emit again when those change. Declarative code doesn’t need to suspend.
👍 3
👍🏾 1
v
Thanks @Zach Klippenstein (he/him) [MOD]
150 Views