Skip to content

Commit af9f971

Browse files
Keep frameTime at 0 always.
1 parent c4b6756 commit af9f971

File tree

1 file changed

+18
-21
lines changed

1 file changed

+18
-21
lines changed

workflow-runtime/src/commonMain/kotlin/com/squareup/workflow1/internal/compose/ComposeWorkflowNodeAdapter.kt

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import com.squareup.workflow1.internal.UnitApplier
2626
import com.squareup.workflow1.internal.WorkflowNodeId
2727
import kotlinx.coroutines.CoroutineStart.ATOMIC
2828
import kotlinx.coroutines.ExperimentalCoroutinesApi
29-
import kotlinx.coroutines.ensureActive
3029
import kotlinx.coroutines.launch
3130
import kotlinx.coroutines.selects.SelectBuilder
3231
import kotlin.coroutines.CoroutineContext
@@ -75,8 +74,6 @@ internal class ComposeWorkflowNodeAdapter<PropsT, OutputT, RenderingT>(
7574
private val recomposerDriver = RecomposerDriver(recomposer)
7675
private val composition: Composition = Composition(UnitApplier, recomposer)
7776

78-
private var frameTimeCounter = 0L
79-
8077
private var cachedComposeWorkflow: ComposeWorkflow<PropsT, OutputT, RenderingT> by
8178
mutableStateOf(workflow)
8279
private var lastProps by mutableStateOf(initialProps)
@@ -94,8 +91,6 @@ internal class ComposeWorkflowNodeAdapter<PropsT, OutputT, RenderingT>(
9491
* not called.
9592
*/
9693
private val processFrameRequestFromChannel: () -> ActionProcessingResult = {
97-
log("frame request received from channel")
98-
9994
// A pure frame request means compose state was updated that the composition read, but
10095
// emitOutput was not called, so we don't have any outputs to report.
10196
val applied = ActionApplied<OutputT>(
@@ -104,7 +99,7 @@ internal class ComposeWorkflowNodeAdapter<PropsT, OutputT, RenderingT>(
10499
)
105100

106101
// Propagate the action up the workflow tree.
107-
log("sending no output to parent: $applied")
102+
log("frame request received from channel, sending no output to parent: $applied")
108103
emitAppliedActionToParent(applied)
109104
}
110105

@@ -119,6 +114,8 @@ internal class ComposeWorkflowNodeAdapter<PropsT, OutputT, RenderingT>(
119114
// We also need to set the composition content before calling startComposition so it doesn't
120115
// need to suspend to wait for it.
121116
composition.setContent {
117+
// childNode isn't snapshot state but that's fine, since when the recomposer is started it
118+
// will always recompose, childNode will be non-null by then, and it will never change again.
122119
val childNode = this.childNode
123120
if (childNode != null) {
124121
val rendering = childNode.produceRendering(
@@ -180,40 +177,43 @@ internal class ComposeWorkflowNodeAdapter<PropsT, OutputT, RenderingT>(
180177
workflow: Workflow<PropsT, OutputT, RenderingT>,
181178
input: PropsT
182179
): RenderingT {
183-
log("render setting props and workflow states")
184180
this.cachedComposeWorkflow = workflow as ComposeWorkflow
185181
this.lastProps = input
186182

187183
// Ensure that recomposer has a chance to process any state changes from the action cascade that
188184
// triggered this render before we check for a frame.
189185
log("render sending apply notifications again needsRecompose=${recomposerDriver.needsRecompose}")
186+
// TODO Consider pulling this up into the workflow runtime loop, since we only need to run it
187+
// once before the entire tree renders, not at every level. In fact, if this is only here to
188+
// ensure cachedComposeWorkflow and lastProps are seen, that will only work if this
189+
// ComposeWorkflow is not nested below another traditional and compose workflow, since anything
190+
// rendering under the first CW will be in a snapshot.
190191
Snapshot.sendApplyNotifications()
191192
log("sent apply notifications, needsRecompose=${recomposerDriver.needsRecompose}")
192193

193194
val initialRender = !lastRendering.isInitialized
194195
if (initialRender) {
195-
// Initial render kicks off the render loop. This should always synchronously request a frame.
196+
// Initial render kicks off the render loop. This should synchronously request a frame.
196197
startComposition()
197198
}
198199

199200
// Synchronously recompose any invalidated composables, if any, and update lastRendering.
200201
// It is very likely that trySendFrame will fail: any time the workflow runtime is doing a
201202
// render pass and no state read by our composition changed, there shouldn't be a frame request.
202-
log("renderFrame with time $frameTimeCounter")
203-
val frameSent = recomposerDriver.tryPerformRecompose(frameTimeCounter)
204-
if (frameSent) {
205-
log("renderFrame finished executing frame with time $frameTimeCounter")
206-
frameTimeCounter++
203+
// Hard-code unchanging frame time since there's no actual frame time and workflow code
204+
// shouldn't rely on this value.
205+
log("renderFrame")
206+
val recomposed = recomposerDriver.tryPerformRecompose(frameTimeNanos = 0L)
207+
if (recomposed) {
208+
log("renderFrame finished executing frame")
207209
} else {
208210
log("no frame request at time of render!")
209211
if (initialRender) {
210212
error("Expected initial composition to synchronously request initial frame.")
211213
}
212214
}
213215

214-
return lastRendering.getOrThrow().also {
215-
log("render returning value: $it")
216-
}
216+
return lastRendering.getOrThrow()
217217
}
218218

219219
override fun snapshot(): TreeSnapshot = childNode!!.snapshot()
@@ -237,14 +237,11 @@ internal class ComposeWorkflowNodeAdapter<PropsT, OutputT, RenderingT>(
237237

238238
@OptIn(ExperimentalCoroutinesApi::class)
239239
private fun startComposition() {
240+
// Launch as atomic to ensure the composition is always disposed, even if our job is cancelled
241+
// before this coroutine has a chance to start running.
240242
launch(start = ATOMIC) {
241243
try {
242-
log("runRecomposeAndApplyChanges")
243244
recomposerDriver.runRecomposeAndApplyChanges()
244-
} catch (e: Throwable) {
245-
log("compose runtime threw: $e\n" + e.stackTraceToString())
246-
ensureActive()
247-
throw e
248245
} finally {
249246
composition.dispose()
250247
}

0 commit comments

Comments
 (0)