@@ -45,7 +45,8 @@ import kotlin.coroutines.CoroutineContext
45
45
private const val OUTPUT_QUEUE_LIMIT = 1_000
46
46
47
47
/* *
48
- * Representation and implementation of a single [ComposeWorkflow].
48
+ * Representation and implementation of a single [ComposeWorkflow] inside a
49
+ * [ComposeWorkflowNodeAdapter].
49
50
*/
50
51
@OptIn(WorkflowExperimentalApi ::class )
51
52
internal class ComposeWorkflowChildNode <PropsT , OutputT , RenderingT >(
@@ -77,8 +78,10 @@ internal class ComposeWorkflowChildNode<PropsT, OutputT, RenderingT>(
77
78
override val sessionId: Long = idCounter.createId()
78
79
79
80
private var lastProps by mutableStateOf(initialProps)
80
- private val saveableStateRegistry: SaveableStateRegistry
81
+
82
+ /* * This does not need to be a snapshot state object, it's only set again by [snapshot]. */
81
83
private var snapshotCache = snapshot?.childTreeSnapshots
84
+ private val saveableStateRegistry: SaveableStateRegistry
82
85
private val childNodes = mutableVectorOf<ComposeChildNode <* , * , * >>()
83
86
84
87
private val outputsChannel = Channel <OutputT >(capacity = OUTPUT_QUEUE_LIMIT )
@@ -121,7 +124,7 @@ internal class ComposeWorkflowChildNode<PropsT, OutputT, RenderingT>(
121
124
122
125
val workflowSnapshot = snapshot?.workflowSnapshot
123
126
var restoredRegistry: SaveableStateRegistry ? = null
124
- // Don't care about this return value, our state is separate .
127
+ // Don't care if the interceptor returns a state value, our state is stored in the composition .
125
128
interceptor.onInitialState(
126
129
props = initialProps,
127
130
snapshot = workflowSnapshot,
@@ -273,7 +276,7 @@ internal class ComposeWorkflowChildNode<PropsT, OutputT, RenderingT>(
273
276
} else {
274
277
// We need to be able to explicitly request recomposition of this composable when an action
275
278
// cascade results in this child changing state because traditional workflows don't know
276
- // about Compose.
279
+ // about Compose. See comment in acceptChildActionResult for more info.
277
280
val recomposeScope = currentRecomposeScope
278
281
remember {
279
282
TraditionalWorkflowAdapterChildNode (
@@ -288,6 +291,11 @@ internal class ComposeWorkflowChildNode<PropsT, OutputT, RenderingT>(
288
291
interceptor = interceptor,
289
292
idCounter = idCounter,
290
293
acceptChildActionResult = { actionApplied ->
294
+ // If this child needs to be re-rendered on the next render pass and there are no other
295
+ // state changes in the compose runtime during this action cascade, if we don't
296
+ // explicitly invalidate the recompose scope then the recomposer will think it doesn't
297
+ // have anything to do and not recompose us, which means we wouldn't have a chance to
298
+ // re-render the traditional workflow.
291
299
if (actionApplied.stateChanged) {
292
300
recomposeScope.invalidate()
293
301
}
@@ -334,20 +342,7 @@ internal class ComposeWorkflowChildNode<PropsT, OutputT, RenderingT>(
334
342
): ActionProcessingResult {
335
343
log(" handling child output: $appliedActionFromChild " )
336
344
val outputFromChild = appliedActionFromChild.output
337
- // if (outputFromChild == null || onOutput == null) {
338
- // // The child didn't actually emit anything or we don't care, so we don't need to
339
- // // propagate anything to the parent. We halt the action cascade by simply returning
340
- // // here without calling emitAppliedActionToParent.
341
- // //
342
- // // NOTE: SubtreeManager has an additional case for PARTIAL_TREE_RENDERING, but we
343
- // // can just assume that using ComposeWorkflow at all implies that optimization.
344
- // //
345
- // // If our child state changed, we need to report that ours did too, as per the
346
- // // comment in StatefulWorkflowNode.applyAction.
347
- // return appliedActionFromChild.withOutput(null)
348
- // }
349
-
350
- // The child DID emit an output, so we need to call our handler, which will zero or
345
+ // The child emitted an output, so we need to call our handler, which will zero or
351
346
// more of two things: (1) change our state, (2) emit an output.
352
347
353
348
// If this workflow calls emitOutput while running child output handler, we don't want
0 commit comments