Pass data in the Modifier tree and beyond
One of the reasons why the order of Modifiers is important could be summed by passing data from one modifier node to other nodes right of it.
Why to the right? You can pass data from a node in the tree to the right along the modifier chain. Modifiers can pass data to all the modifiers to the right using Modifier.modifierLocalProvider(key) { value }
. Modifiers can retrieve and update data using Modifier.modifierLocalConsumer { }
. The lambda block of the consumer will be called each time the state (attached, detached, etc.), the order of the modifier nodes, or the provided data changes.
Similar to CompositionLocal
, ModifierLocal
works the same way but in the modifier tree.
Let’s look at this example where we declare our ModifierLocal
to allow other modifiers in the tree to pass the instance of MyScope
.
You can notice that passed modifier
is concatenated last in the chain, to the right of the modifier that starts the chain and to the right of modifierLocalProvider { }
.
Modifier.fillMaxSize()
.modifierLocalProvider(ModifierLocalMyScope) { scope }
.then(modifier)
Within Modifier tree
There are two ways to read data from ModifierLocal
s: using modifierLocalConsumer { }
or implementing ModifierLocalConsumer
. The ModifierLocalConsumer
interface has an onModifierLocalsUpdated
function that is called whenever there is a change in the modifier order or local data. By implementing this interface, you can delegate the task of passing data to other modifier implementations.
Beyond Modifier tree
As the passed modifier is added last, we can get an instance of the scope at the calling site and use it in the composition context. By setting the passed modifier last in the chain, you can pass data up from the modifier tree to higher levels and even interact with the composition context.
Observing changes in the Locals within the modifier trees allows us to get an instance and use it in the composition context later.
.modifierLocalConsumer {
myScope = ModifierLocalMyScope.current
}