Slide 72
Slide 72 text
@zachklipp
/**
* Renders [rendering] into the composition using this [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(
* 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)
}
}
}
}