1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.compose.ui.node
18 
19 import androidx.compose.ui.Modifier
20 
21 /**
22  * [Modifier.Node]s that implement ObserverNode can provide their own implementation of
23  * [onObservedReadsChanged] that will be called in response to changes to snapshot objects read
24  * within an [observeReads] block.
25  */
26 interface ObserverModifierNode : DelegatableNode {
27 
28     /**
29      * This callback is called when any values that are read within the [observeReads] block change.
30      * It is called after the snapshot is committed. [onObservedReadsChanged] is called on the UI
31      * thread, and only called once in response to snapshot observation. To continue observing
32      * further updates, you need to call [observeReads] again.
33      */
onObservedReadsChangednull34     fun onObservedReadsChanged()
35 }
36 
37 internal class ObserverNodeOwnerScope(internal val observerNode: ObserverModifierNode) :
38     OwnerScope {
39     override val isValidOwnerScope: Boolean
40         get() = observerNode.node.isAttached
41 
42     companion object {
43         internal val OnObserveReadsChanged: (ObserverNodeOwnerScope) -> Unit = {
44             if (it.isValidOwnerScope) it.observerNode.onObservedReadsChanged()
45         }
46     }
47 }
48 
49 /**
50  * Use this function to observe snapshot reads for any target within the specified [block].
51  * [ObserverModifierNode.onObservedReadsChanged] is called when any of the observed values within
52  * the snapshot change.
53  */
observeReadsnull54 fun <T> T.observeReads(block: () -> Unit) where T : Modifier.Node, T : ObserverModifierNode {
55     val target = ownerScope ?: ObserverNodeOwnerScope(this).also { ownerScope = it }
56     requireOwner()
57         .snapshotObserver
58         .observeReads(
59             target = target,
60             onChanged = ObserverNodeOwnerScope.OnObserveReadsChanged,
61             block = block
62         )
63 }
64