Whats the recommended way to compute values in com...
# compose
z
Whats the recommended way to compute values in compose? If I have a
Lazy<Foo>
in my MainActivity that takes 1000 ms to resolve; how can I
.get()
it inside a
@Composable
function such that it happens in the background (e.g. with
Dispatchers.Default
)?
t
You need to find a way to convert your Lazy<Foo> into something like State<Foo?>, that starts with null, and gets updated from a coroutine. For this, you can use Side Effects (https://developer.android.com/jetpack/compose/side-effects). The easiest to implement in your case should be
produceState
. Or you could create a
StateFlow
in the viewModel, launch a coroutine and update the value, and collect it as state in the
@Composable
function.
z
Something like this? Im doing this before viewmodels (etc) get into the picture, it just takes a while to create the dependency graph.
Copy code
@Composable
private fun rootController(
    context: Context
): RootController? {
    val controller by produceState<RootController?>(
        initialValue = null,
        producer = {
            value = withContext(Default) {
                PhoneComponent
                    .get(context)
                    .rootController()
            }
        }
    )

    return controller
}
t
Yes, exactly. But the second approach with StateFlow being collected as State is best in most situations
So you’d do something like:
Copy code
private fun getRootControllerFlow(context: Context) = 
  flow { emit(PhoneComponent.get(context)) }
  .flowOn(Dispatchers.Default)
  .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)

@Composable
fun Screen() {
  val rootController by getRootControllerFlow(LocalContext.current).collectAsState()
}
z
I think the flow variant breaks due to a new flow being created everytime the function is recomposed?
t
You’re right, it should be
Copy code
val context = LocalContext.current
val rootController by remember(context) { getRootControllerFlow(context) }.collectAsState()
z
That works 👍🏽 If you dont mind elaborating, how is this better than
produceState
?