[ViewEnvironment]'s [ViewRegistry] to * generate the view. * * This function fulf i lls a similar role as [WorkflowViewStub], but is much more convenient to use * from Composable functions. Note, however, that just like [WorkflowViewStub], it doesn't matter * whether the factory registered for the rendering is using classic Android views or Compose. * * # # Example * * ` ` ` * data class FramedRendering<R : Any>( * val borderColor: Color, * val child: R * ) : ComposeRendering { * * @Composable override fun Content(viewEnvironment: ViewEnvironment) { * Surface(border = Border(borderColor, 8.dp)) { * WorkflowRendering(child, viewEnvironment) * } * } * } * ` ` ` * * @param rendering The workflow rendering to display. May be of any type for which a [ViewFactory] * has been registered in [viewEnvironment]'s [ViewRegistry]. * @param modif i er A [Modif i er] that will be applied to composable used to show [rendering]. * * @throws I l l egalArgumentException if no factory can be found for [rendering]'s type. * / @WorkflowUiExperimentalApi @Composable public fun WorkflowRendering( rendering: Any, viewEnvironment: ViewEnvironment, modif i er: Modif i er = Modif i er ) { / / This will fetch a new view factory any time the new rendering is incompatible with the previous / / one, as determined by Compatible. This corresponds to WorkflowViewStub's canShowRendering / / check. val renderingCompatibilityKey = Compatible.keyFor(rendering) / / By surrounding the below code with this key function, any time the new rendering is not / / compatible with the previous rendering we'll tear down the previous subtree of the composition, / / including its lifecycle, which destroys the lifecycle and any remembered state. If the view / / factory created an Android view, this will also remove the old one from the view hierarchy / / before replacing it with the new one. key(renderingCompatibilityKey) { val viewFactory = remember { / / The view registry may return a new factory instance for a rendering every time we ask it, for / / example if an AndroidViewRendering doesn't share its factory between rendering instances. We / / intentionally don't ask it for a new instance every time to match the behavior of / / WorkflowViewStub and other containers, which only ask for a new factory when the rendering is / / incompatible. viewEnvironment[ViewRegistry] / / Can't use ViewRegistry.buildView here since we need the factory to convert it to a / / compose one. .getFactoryForRendering(rendering) .asComposeViewFactory() } / / Just like WorkflowViewStub, we need to manage a Lifecycle for the child view. We just provide / / a local here – ViewFactoryAndroidView will handle setting the appropriate view tree owners / / on the child view when necessary. Because this function is surrounded by a key() call, when / / the rendering is incompatible, the lifecycle for the old view will be destroyed. val lifecycleOwner = rememberChildLifecycleOwner() CompositionLocalProvider(LocalLifecycleOwner provides lifecycleOwner) { / / We need to propagate min constraints because one of the likely uses for the modif i er passed / / into this function is to directly control the layout of the child view – which means / / minimum constraints are likely to be signif i cant. Box(modif i er, propagateMinConstraints = true) { viewFactory.Content(rendering, viewEnvironment) } } } }