Modifier.Node
-
Cmn
abstract class Modifier.Node : DelegatableNode
DelegatingNode |
A |
The longer-lived object that is created for each Modifier.Element applied to a androidx.compose.ui.layout.Layout. Most Modifier.Node implementations will have a corresponding "Modifier Factory" extension method on Modifier that will allow them to be used indirectly, without ever implementing a Modifier.Node subclass directly. In some cases it may be useful to define a custom Modifier.Node subclass in order to efficiently implement some collection of behaviors that requires maintaining state over time and over many recompositions where the various provided Modifier factories are not sufficient.
When a Modifier is set on a androidx.compose.ui.layout.Layout, each Modifier.Element contained in that linked list will result in a corresponding Modifier.Node instance in a matching linked list of Modifier.Nodes that the androidx.compose.ui.layout.Layout will hold on to. As subsequent Modifier chains get set on the androidx.compose.ui.layout.Layout, the linked list of Modifier.Nodes will be diffed and updated as appropriate, even though the Modifier instance might be completely new. As a result, the lifetime of a Modifier.Node is the intersection of the lifetime of the androidx.compose.ui.layout.Layout that it lives on and a corresponding Modifier.Element being present in the androidx.compose.ui.layout.Layout's Modifier.
If one creates a subclass of Modifier.Node, it is expected that it will implement one or more interfaces that interact with the various Compose UI subsystems. To use the Modifier.Node subclass, it is expected that it will be instantiated by adding a androidx.compose.ui.node.ModifierNodeElement to a Modifier chain.
Summary
Public constructors |
|
|---|---|
Node() |
Cmn
|
Public functions |
||
|---|---|---|
open Unit |
onAttach()Called when the node is attached to a |
Cmn
|
open Unit |
onDetach()Called when the node is not attached to a |
Cmn
|
open Unit |
onReset()Called when the node is about to be moved to a pool of layouts ready to be reused. |
Cmn
|
Unit |
sideEffect(effect: () -> Unit)This can be called to register |
Cmn
|
Public properties |
||
|---|---|---|
CoroutineScope |
A |
Cmn
|
Boolean |
Indicates that the node is attached to a |
Cmn
|
final Modifier.Node |
A reference of the |
Cmn
|
open Boolean |
If this property returns |
Cmn
|
Inherited functions |
|---|
Public constructors
Public functions
onAttach
open fun onAttach(): Unit
Called when the node is attached to a androidx.compose.ui.layout.Layout which is part of the UI tree. When called, node is guaranteed to be non-null. You can call sideEffect, coroutineScope, etc. This is not guaranteed to get called at a time where the rest of the Modifier.Nodes in the hierarchy are "up to date". For instance, at the time of calling onAttach for this node, another node may be in the tree that will be detached by the time Compose has finished applying changes. As a result, if you need to guarantee that the state of the tree is "final" for this round of changes, you should use the sideEffect API to schedule the calculation to be done at that time.
onDetach
open fun onDetach(): Unit
Called when the node is not attached to a androidx.compose.ui.layout.Layout which is not a part of the UI tree anymore. Note that the node can be reattached again.
This should be called right before the node gets removed from the list, so you should still be able to traverse inside of this method. Ideally we would not allow you to trigger side effects here.
onReset
open fun onReset(): Unit
Called when the node is about to be moved to a pool of layouts ready to be reused. For example it happens when the node is part of the item of LazyColumn after this item is scrolled out of the viewport. This means this node could be in future reused for a androidx.compose.ui.layout.Layout displaying a semantically different content when the list will be populating a new item.
Use this callback to reset some local item specific state, like "is my component focused".
This callback is called while the node is attached. Right after this callback the node will be detached and later reattached when reused.
import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.Modifier class SelectableNode : Modifier.Node() { var selected by mutableStateOf(false) override fun onReset() { // reset `selected` to the initial value as if the node will be reused for // displaying different content it shouldn't be selected straight away. selected = false } // some logic which sets `selected` to true when it is selected }
sideEffect
fun sideEffect(effect: () -> Unit): Unit
This can be called to register effect as a function to be executed after all of the changes to the tree are applied.
This API can only be called if the node isAttached.
Public properties
coroutineScope
val coroutineScope: CoroutineScope
A CoroutineScope that can be used to launch tasks that should run while the node is attached.
The scope is accessible between onAttach and onDetach calls, and will be cancelled after the node is detached (after onDetach returns).
import androidx.compose.animation.core.Animatable import androidx.compose.ui.Modifier class AnimatedNode : Modifier.Node() { val animatable = Animatable(0f) override fun onAttach() { coroutineScope.launch { animatable.animateTo(1f) } } }
| Throws | |
|---|---|
kotlin.IllegalStateException |
If called while the node is not attached. |
isAttached
val isAttached: Boolean
Indicates that the node is attached to a androidx.compose.ui.layout.Layout which is part of the UI tree. This will get set to true right before onAttach is called, and set to false right after onDetach is called.
node
final val node: Modifier.Node
A reference of the Modifier.Node that holds this node's position in the node hierarchy. If the node is a delegate of another node, this will point to the root delegating node that is actually part of the node tree. Otherwise, this will point to itself.
shouldAutoInvalidate
open val shouldAutoInvalidate: Boolean
If this property returns true, then nodes will be automatically invalidated after the modifier update completes (For example, if the returned Node is a DrawModifierNode, its DrawModifierNode.invalidateDraw function will be invoked automatically as part of auto invalidation).
This is enabled by default, and provides a convenient mechanism to schedule invalidation and apply changes made to the modifier. You may choose to set this to false if your modifier has auto-invalidatable properties that do not frequently require invalidation to improve performance by skipping unnecessary invalidation. If autoInvalidate is set to false, you must call the appropriate invalidate functions manually when the modifier is updated or else the updates may not be reflected in the UI appropriately.