renderAsState

fun <PropsT, OutputT : Any, RenderingT> Workflow<PropsT, OutputT, RenderingT>.renderAsState(props: PropsT, interceptors: List<WorkflowInterceptor> = emptyList(), scope: CoroutineScope = rememberCoroutineScope(), runtimeConfig: RuntimeConfig = RuntimeConfigOptions.DEFAULT_CONFIG, onOutput: suspend (OutputT) -> Unit): State<RenderingT>

Runs this Workflow as long as this composable is part of the composition, and returns a State object that will be updated whenever the runtime emits a new RenderingT. Note that here, and in the rest of the documentation for this class, the "State" type refers to Compose's snapshot State type, not the concept of the StateT type in a particular workflow.

The workflow runtime will be started when this function is first added to the composition, and cancelled when it is removed or if the composition fails. The first rendering will be available immediately as soon as this function returns as State.value. Composables that read this value will automatically recompose whenever the runtime emits a new rendering. If you are driving UI from the Workflow tree managed by renderAsState then you will probably want to pass the returned State's value (which is the Workflow rendering) to the WorkflowRendering composable.

Snapshots from the runtime will automatically be saved and restored using Compose's rememberSaveable.

Example

private val appViewRegistry = ViewRegistry(…)

@Composable fun App(workflow: Workflow<…>, props: Props) {
val scaffoldState = …

// Run the workflow in the current composition's coroutine scope.
val rendering by workflow.renderAsState(props, onOutput = { output ->
// Note that onOutput is a suspend function, so you can run animations
// and call other suspend functions.
scaffoldState.snackbarHostState
.showSnackbar(output.toString())
})
val viewEnvironment = remember {
ViewEnvironment(mapOf(ViewRegistry to appViewRegistry))
}

Scaffold(…) { padding ->
// Display the root rendering using the view environment's ViewRegistry.
WorkflowRendering(rendering, viewEnvironment, Modifier.padding(padding))
}
}

Caveat on threading and composition

Note that the initial render pass will occur on whatever thread this function is called from. That may be a background thread, as Compose supports performing composition on background threads. Well-behaved workflows should have pure initialState and render functions, so this should not be a problem. Any side effects performed by workflows using the runningSideEffect method or Workers will be executed in scope as usual.

Also note that composition is an operation that may fail, or be cancelled, and the "result" of a given composition pass may be thrown away and never used to update UI. When this happens, the composition is said to have failed to commit. If the composition that initializes a workflow runtime using this function fails to commit, the runtime will be started and then immediately cancelled. Since the workflow runtime may perform side effects, this may cause effects that look like they spontaneously occur, or happen more often than they should.

Receiver

The Workflow to run. If the value of the receiver changes to a different Workflow while this function is in the composition, the runtime will be restarted with the new workflow.

Parameters

props

The PropsT for the root Workflow. Changes to this value across different compositions will cause the root workflow to re-render with the new props.

interceptors

An optional list of WorkflowInterceptors that will wrap every workflow rendered by the runtime. Interceptors will be invoked in 0-to-length order: the interceptor at index 0 will process the workflow first, then the interceptor at index 1, etc.

scope

The CoroutineScope in which to launch the workflow runtime. If not specified, the value of rememberCoroutineScope will be used. Any exceptions thrown in any workflows, after the initial render pass, will be handled by this scope, and cancelling this scope will cancel the workflow runtime and any running workers. Note that any dispatcher in this scope will not be used to execute the very first render pass.

runtimeConfig

The RuntimeConfig for the Workflow runtime started to power this state.

onOutput

A function that will be executed whenever the root Workflow emits an output.