ControlledComposition
Function
Common
@TestOnly
public fun ControlledComposition(
applier: Applier<*>,
parent: CompositionContext,
): ControlledComposition
This method is a way to initiate a composition. Optionally, a parent CompositionContext can
be provided to make the composition behave as a sub-composition of the parent or a Recomposer
can be provided.
A controlled composition allows direct control of the composition instead of it being controlled
by the Recomposer passed ot the root composition.
It is important to call Composition.dispose this composer is no longer needed in order to
release resources.
Parameters
| applier | The Applier instance to be used in the composition. |
| parent | The parent CompositionContext. |
Common
@TestOnly
@ExperimentalComposeApi
public fun ControlledComposition(
applier: Applier<*>,
parent: CompositionContext,
recomposeCoroutineContext: CoroutineContext,
): ControlledComposition
Code Examples
CustomTreeComposition
@Suppress("unused")
fun CustomTreeComposition() {
// Provided we have a tree with a node base type like the following
abstract class Node {
val children = mutableListOf<Node>()
}
// We would implement an Applier class like the following, which would teach compose how to
// manage a tree of Nodes.
class NodeApplier(root: Node) : AbstractApplier<Node>(root) {
override fun insertTopDown(index: Int, instance: Node) {
current.children.add(index, instance)
}
override fun insertBottomUp(index: Int, instance: Node) {
// Ignored as the tree is built top-down.
}
override fun remove(index: Int, count: Int) {
current.children.remove(index, count)
}
override fun move(from: Int, to: Int, count: Int) {
current.children.move(from, to, count)
}
override fun onClear() {
root.children.clear()
}
}
// A function like the following could be created to create a composition provided a root Node.
fun Node.setContent(parent: CompositionContext, content: @Composable () -> Unit): Composition {
return Composition(NodeApplier(this), parent).apply { setContent(content) }
}
// assuming we have Node sub-classes like "TextNode" and "GroupNode"
class TextNode : Node() {
var text: String = ""
var onClick: () -> Unit = {}
}
class GroupNode : Node()
// Composable equivalents could be created
@Composable
fun Text(text: String, onClick: () -> Unit = {}) {
ComposeNode<TextNode, NodeApplier>(::TextNode) {
set(text) { this.text = it }
set(onClick) { this.onClick = it }
}
}
@Composable
fun Group(content: @Composable () -> Unit) {
ComposeNode<GroupNode, NodeApplier>(::GroupNode, {}, content)
}
// and then a sample tree could be composed:
fun runApp(root: GroupNode, parent: CompositionContext) {
root.setContent(parent) {
var count by remember { mutableStateOf(0) }
Group {
Text("Count: $count")
Text("Increment") { count++ }
}
}
}
}
