|
3 | 3 |
|
4 | 4 | package com.squareup.workflow1
|
5 | 5 |
|
6 |
| -import kotlin.LazyThreadSafetyMode.NONE |
7 | 6 | import kotlin.jvm.JvmMultifileClass
|
8 | 7 | import kotlin.jvm.JvmName
|
9 | 8 |
|
@@ -33,11 +32,43 @@ public abstract class StatelessWorkflow<in PropsT, out OutputT, out RenderingT>
|
33 | 32 | ) : BaseRenderContext<@UnsafeVariance PropsT, Nothing, @UnsafeVariance OutputT> by
|
34 | 33 | baseContext as BaseRenderContext<PropsT, Nothing, OutputT>
|
35 | 34 |
|
36 |
| - @Suppress("UNCHECKED_CAST") |
37 |
| - private val statefulWorkflow = Workflow.stateful<PropsT, Unit, OutputT, RenderingT>( |
38 |
| - initialState = { Unit }, |
39 |
| - render = { props, _ -> render(props, RenderContext(this, this@StatelessWorkflow)) } |
40 |
| - ) |
| 35 | + private val statefulWorkflow: StatefulWorkflow<PropsT, Unit, OutputT, RenderingT> = |
| 36 | + object : StatefulWorkflow<PropsT, Unit, OutputT, RenderingT>() { |
| 37 | + // We want to cache the render context so that we don't have to recreate it each time |
| 38 | + // render() is called. |
| 39 | + private var cachedStatelessRenderContext: |
| 40 | + StatelessWorkflow<PropsT, OutputT, RenderingT>.RenderContext? = null |
| 41 | + |
| 42 | + // We must know if the RenderContext we are passed (which is a StatefulWorkflow.RenderContext) |
| 43 | + // has changed, so keep track of it. |
| 44 | + private var canonicalStatefulRenderContext: |
| 45 | + StatefulWorkflow<PropsT, Unit, OutputT, RenderingT>.RenderContext? = null |
| 46 | + |
| 47 | + override fun initialState( |
| 48 | + props: PropsT, |
| 49 | + snapshot: Snapshot? |
| 50 | + ) = Unit |
| 51 | + |
| 52 | + override fun render( |
| 53 | + renderProps: PropsT, |
| 54 | + renderState: Unit, |
| 55 | + context: RenderContext |
| 56 | + ): RenderingT { |
| 57 | + // The `RenderContext` used *might* change - primarily in the case of our tests. E.g., The |
| 58 | + // `RenderTester` uses a special NoOp context to render twice to test for idempotency. |
| 59 | + // In order to support a changed render context but keep caching, we check to see if the |
| 60 | + // instance passed in has changed. |
| 61 | + if (cachedStatelessRenderContext == null || context !== canonicalStatefulRenderContext) { |
| 62 | + // Recreate it if the StatefulWorkflow.RenderContext we are passed has changed. |
| 63 | + cachedStatelessRenderContext = RenderContext(context, this@StatelessWorkflow) |
| 64 | + } |
| 65 | + canonicalStatefulRenderContext = context |
| 66 | + // Pass the StatelessWorkflow.RenderContext to our StatelessWorkflow. |
| 67 | + return render(renderProps, cachedStatelessRenderContext!!) |
| 68 | + } |
| 69 | + |
| 70 | + override fun snapshotState(state: Unit): Snapshot? = null |
| 71 | + } |
41 | 72 |
|
42 | 73 | /**
|
43 | 74 | * Called at least once any time one of the following things happens:
|
@@ -69,9 +100,6 @@ public abstract class StatelessWorkflow<in PropsT, out OutputT, out RenderingT>
|
69 | 100 | /**
|
70 | 101 | * Satisfies the [Workflow] interface by wrapping `this` in a [StatefulWorkflow] with `Unit`
|
71 | 102 | * state.
|
72 |
| - * |
73 |
| - * This method is called a few times per instance, but we don't need to allocate a new |
74 |
| - * [StatefulWorkflow] every time, so we store it in a private property. |
75 | 103 | */
|
76 | 104 | final override fun asStatefulWorkflow(): StatefulWorkflow<PropsT, *, OutputT, RenderingT> =
|
77 | 105 | statefulWorkflow
|
|
0 commit comments