Google is committed to advancing racial equity for Black communities. See how.

AbstractApplier

abstract class AbstractApplier<T> : Applier<T>
kotlin.Any
   ↳ androidx.compose.runtime.AbstractApplier

An abstract Applier implementation that builds the tree "top down".

import androidx.compose.runtime.compositionFor
import androidx.compose.runtime.emit
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

// 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 insert(index: Int, instance: Node) {
        current.children.add(index, instance)
    }

    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(content: @Composable () -> Unit): Composition {
    return compositionFor(this, NodeApplier(this), Recomposer.current()).also {
        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 = {}) {
    emit<TextNode, NodeApplier>(::TextNode) {
        set(text) { this.text = it }
        set(onClick) { this.onClick = it }
    }
}

@Composable fun Group(content: @Composable () -> Unit) {
    emit<GroupNode, NodeApplier>(::GroupNode, {}, content)
}

// and then a sample tree could be composed:
fun runApp(root: GroupNode) {
    root.setContent {
        var count by remember { mutableStateOf(0) }
        Group {
            Text("Count: $count")
            Text("Increment") { count++ }
        }
    }
}

Summary

Public constructors
<init>(root: T)

An abstract Applier implementation that builds the tree "top down".

Public methods
Unit

Move to the root and remove all nodes from the root, preparing both this Applier and its root to be used as the target of a new composition in the future.

open Unit
down(node: T)

Indicates that the applier is getting traversed "down" the tree.

open Unit
up()

Indicates that the applier is getting traversed "up" the tree.

Protected methods
Unit
MutableList<T>.move(from: Int, to: Int, count: Int)

abstract Unit

Called to perform clearing of the root when clear is called.

Unit
MutableList<T>.remove(index: Int, count: Int)

Inherited functions
Properties
open T

The node that operations will be applied on at any given time.

T

Public constructors

<init>

AbstractApplier(root: T)

An abstract Applier implementation that builds the tree "top down".

import androidx.compose.runtime.compositionFor
import androidx.compose.runtime.emit
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

// 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 insert(index: Int, instance: Node) {
        current.children.add(index, instance)
    }

    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(content: @Composable () -> Unit): Composition {
    return compositionFor(this, NodeApplier(this), Recomposer.current()).also {
        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 = {}) {
    emit<TextNode, NodeApplier>(::TextNode) {
        set(text) { this.text = it }
        set(onClick) { this.onClick = it }
    }
}

@Composable fun Group(content: @Composable () -> Unit) {
    emit<GroupNode, NodeApplier>(::GroupNode, {}, content)
}

// and then a sample tree could be composed:
fun runApp(root: GroupNode) {
    root.setContent {
        var count by remember { mutableStateOf(0) }
        Group {
            Text("Count: $count")
            Text("Increment") { count++ }
        }
    }
}

Public methods

clear

fun clear(): Unit

Move to the root and remove all nodes from the root, preparing both this Applier and its root to be used as the target of a new composition in the future.

down

open fun down(node: T): Unit

Indicates that the applier is getting traversed "down" the tree. When this gets called, node is expected to be a child of current, and after this operation, node is expected to be the new current.

up

open fun up(): Unit

Indicates that the applier is getting traversed "up" the tree. After this operation completes, the current should return the "parent" of the current node at the beginning of this operation.

Protected methods

move

protected fun MutableList<T>.move(
    from: Int,
    to: Int,
    count: Int
): Unit

onClear

protected abstract fun onClear(): Unit

Called to perform clearing of the root when clear is called.

remove

protected fun MutableList<T>.remove(
    index: Int,
    count: Int
): Unit

Properties

current

open var current: T

The node that operations will be applied on at any given time. It is expected that the value of this property will change as down and up are called.

root

val root: T