1 /* <lambda>null2 * Copyright 2020 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.runtime.snapshots.SnapshotStateObserver 20 21 /** 22 * Performs snapshot observation for blocks like draw and layout which should be re-invoked 23 * automatically when the snapshot value has been changed. 24 */ 25 @Suppress("CallbackName") // TODO rename this and SnapshotStateObserver. b/173401548 26 internal class OwnerSnapshotObserver(onChangedExecutor: (callback: () -> Unit) -> Unit) { 27 28 private val observer = SnapshotStateObserver(onChangedExecutor) 29 30 private val onCommitAffectingLookaheadMeasure: (LayoutNode) -> Unit = { layoutNode -> 31 if (layoutNode.isValidOwnerScope) { 32 layoutNode.requestLookaheadRemeasure() 33 } 34 } 35 36 private val onCommitAffectingMeasure: (LayoutNode) -> Unit = { layoutNode -> 37 if (layoutNode.isValidOwnerScope) { 38 layoutNode.requestRemeasure() 39 } 40 } 41 42 private val onCommitAffectingSemantics: (LayoutNode) -> Unit = { layoutNode -> 43 if (layoutNode.isValidOwnerScope) { 44 layoutNode.invalidateSemantics() 45 } 46 } 47 48 private val onCommitAffectingLayout: (LayoutNode) -> Unit = { layoutNode -> 49 if (layoutNode.isValidOwnerScope) { 50 layoutNode.requestRelayout() 51 } 52 } 53 54 private val onCommitAffectingLayoutModifier: (LayoutNode) -> Unit = { layoutNode -> 55 if (layoutNode.isValidOwnerScope) { 56 layoutNode.requestRelayout() 57 } 58 } 59 60 private val onCommitAffectingLayoutModifierInLookahead: (LayoutNode) -> Unit = { layoutNode -> 61 if (layoutNode.isValidOwnerScope) { 62 layoutNode.requestLookaheadRelayout() 63 } 64 } 65 66 private val onCommitAffectingLookahead: (LayoutNode) -> Unit = { layoutNode -> 67 if (layoutNode.isValidOwnerScope) { 68 layoutNode.requestLookaheadRelayout() 69 } 70 } 71 72 /** Observe snapshot reads during layout of [node], executed in [block]. */ 73 internal fun observeLayoutSnapshotReads( 74 node: LayoutNode, 75 affectsLookahead: Boolean = true, 76 block: () -> Unit 77 ) { 78 if (affectsLookahead && node.lookaheadRoot != null) { 79 observeReads(node, onCommitAffectingLookahead, block) 80 } else { 81 observeReads(node, onCommitAffectingLayout, block) 82 } 83 } 84 85 /** Observe snapshot reads during layout of [node]'s LayoutModifiers, executed in [block]. */ 86 internal fun observeLayoutModifierSnapshotReads( 87 node: LayoutNode, 88 affectsLookahead: Boolean = true, 89 block: () -> Unit 90 ) { 91 if (affectsLookahead && node.lookaheadRoot != null) { 92 observeReads(node, onCommitAffectingLayoutModifierInLookahead, block) 93 } else { 94 observeReads(node, onCommitAffectingLayoutModifier, block) 95 } 96 } 97 98 /** Observe snapshot reads during measure of [node], executed in [block]. */ 99 internal fun observeMeasureSnapshotReads( 100 node: LayoutNode, 101 affectsLookahead: Boolean = true, 102 block: () -> Unit 103 ) { 104 if (affectsLookahead && node.lookaheadRoot != null) { 105 observeReads(node, onCommitAffectingLookaheadMeasure, block) 106 } else { 107 observeReads(node, onCommitAffectingMeasure, block) 108 } 109 } 110 111 internal fun observeSemanticsReads(node: LayoutNode, block: () -> Unit) { 112 observeReads(node, onCommitAffectingSemantics, block) 113 } 114 115 /** 116 * Observe snapshot reads for any target, allowing consumers to determine how to respond to 117 * state changes. 118 */ 119 internal fun <T : OwnerScope> observeReads( 120 target: T, 121 onChanged: (T) -> Unit, 122 block: () -> Unit 123 ) { 124 observer.observeReads(target, onChanged, block) 125 } 126 127 internal fun clearInvalidObservations() { 128 observer.clearIf { !(it as OwnerScope).isValidOwnerScope } 129 } 130 131 internal fun clear(target: Any) { 132 observer.clear(target) 133 } 134 135 internal fun startObserving() { 136 observer.start() 137 } 138 139 internal fun stopObserving() { 140 observer.stop() 141 observer.clear() 142 } 143 } 144