@@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
12
12
import kotlinx.coroutines.flow.StateFlow
13
13
import kotlinx.coroutines.isActive
14
14
import kotlinx.coroutines.launch
15
+ import kotlinx.coroutines.yield
15
16
16
17
/* *
17
18
* Launches the [workflow] in a new coroutine in [scope] and returns a [StateFlow] of its
@@ -170,15 +171,15 @@ public fun <PropsT, OutputT, RenderingT> renderWorkflowIn(
170
171
}
171
172
172
173
scope.launch {
173
- while (isActive) {
174
+ outer@ while (isActive) {
174
175
// It might look weird to start by processing an action before getting the rendering below,
175
176
// but remember the first render pass already occurred above, before this coroutine was even
176
177
// launched.
177
178
var actionResult: ActionProcessingResult = runner.processAction()
178
179
179
180
if (shouldShortCircuitForUnchangedState(actionResult)) {
180
181
sendOutput(actionResult, onOutput)
181
- continue
182
+ continue @outer
182
183
}
183
184
184
185
// After resuming from runner.processAction() our coroutine could now be cancelled, check so
@@ -189,15 +190,22 @@ public fun <PropsT, OutputT, RenderingT> renderWorkflowIn(
189
190
var nextRenderAndSnapshot: RenderingAndSnapshot <RenderingT > = runner.nextRendering()
190
191
191
192
if (runtimeConfig.contains(CONFLATE_STALE_RENDERINGS )) {
192
- while (isActive && actionResult is ActionApplied <* > && actionResult.output == null ) {
193
+ conflate@ while (isActive && actionResult is ActionApplied <* > && actionResult.output == null ) {
194
+ // We start by yielding, because if we are on an Unconfined dispatcher, we want to give
195
+ // other signals (like Workers listening to the same result) a chance to get dispatched
196
+ // and queue their actions.
197
+ yield ()
193
198
// We may have more actions we can process, this rendering could be stale.
194
199
actionResult = runner.processAction(waitForAnAction = false )
195
200
196
201
// If no actions processed, then no new rendering needed. Pass on to UI.
197
- if (actionResult == ActionsExhausted ) break
202
+ if (actionResult == ActionsExhausted ) break @conflate
198
203
199
204
// Skip rendering if we had unchanged state, keep draining actions.
200
- if (shouldShortCircuitForUnchangedState(actionResult)) continue
205
+ if (shouldShortCircuitForUnchangedState(actionResult)) {
206
+ sendOutput(actionResult, onOutput)
207
+ continue @outer
208
+ }
201
209
202
210
// Make sure the runtime has not been cancelled from runner.processAction()
203
211
if (! isActive) return @launch
0 commit comments