-
Notifications
You must be signed in to change notification settings - Fork 112
Reimplemented Workers using side effects (GUWT). #110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,8 @@ package com.squareup.workflow | |
|
|
||
| import com.squareup.workflow.WorkflowAction.Companion.noAction | ||
| import com.squareup.workflow.WorkflowAction.Updater | ||
| import kotlin.reflect.KType | ||
| import kotlin.reflect.typeOf | ||
|
|
||
| /** | ||
| * Facilities for a [Workflow] to interact with other [Workflow]s and the outside world from inside | ||
|
|
@@ -109,19 +111,6 @@ interface RenderContext<out PropsT, StateT, in OutputT> { | |
| handler: (ChildOutputT) -> WorkflowAction<PropsT, StateT, OutputT> | ||
| ): ChildRenderingT | ||
|
|
||
| /** | ||
| * Ensures [worker] is running. When the [Worker] emits an output, [handler] is called | ||
| * to determine the [WorkflowAction] to take. When the worker finishes, nothing happens (although | ||
| * another render pass may be triggered). | ||
| * | ||
| * @param key An optional string key that is used to distinguish between identical [Worker]s. | ||
| */ | ||
| fun <T> runningWorker( | ||
| worker: Worker<T>, | ||
| key: String = "", | ||
| handler: (T) -> WorkflowAction<PropsT, StateT, OutputT> | ||
| ) | ||
|
|
||
| /** | ||
| * Ensures [sideEffect] is running with the given [key]. | ||
| * | ||
|
|
@@ -196,12 +185,62 @@ fun <PropsT, StateT, OutputT> RenderContext<PropsT, StateT, OutputT>.runningWork | |
| worker: Worker<Nothing>, | ||
| key: String = "" | ||
| ) { | ||
| // Need to cast to Any so the compiler doesn't complain about unreachable code. | ||
| runningWorker(worker as Worker<Any>, key) { | ||
| runningWorker(worker, key) { | ||
| // The compiler thinks this code is unreachable, and it is correct. But we have to pass a lambda | ||
| // here so we might as well check at runtime as well. | ||
| @Suppress("UNREACHABLE_CODE", "ThrowableNotThrown") | ||
| throw AssertionError("Worker<Nothing> emitted $it") | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Ensures [worker] is running. When the [Worker] emits an output, [handler] is called | ||
| * to determine the [WorkflowAction] to take. When the worker finishes, nothing happens (although | ||
| * another render pass may be triggered). | ||
| * | ||
| * Like workflows, workers are kept alive across multiple render passes if they're the same type, | ||
| * and different workers of distinct types can be run concurrently. However, unlike workflows, | ||
| * workers are compared by their _declared_ type, not their actual type. This means that if you | ||
| * pass a worker stored in a variable to this function, the type that will be used to compare the | ||
| * worker will be the type of the variable, not the type of the object the variable refers to. | ||
| * | ||
| * @param key An optional string key that is used to distinguish between identical [Worker]s. | ||
| */ | ||
| @OptIn(ExperimentalStdlibApi::class) | ||
| /* ktlint-disable parameter-list-wrapping */ | ||
| inline fun <T, reified W : Worker<T>, PropsT, StateT, OutputT> | ||
| RenderContext<PropsT, StateT, OutputT>.runningWorker( | ||
| worker: W, | ||
| key: String = "", | ||
| noinline handler: (T) -> WorkflowAction<PropsT, StateT, OutputT> | ||
| ) { | ||
| /* ktlint-enable parameter-list-wrapping */ | ||
| runningWorker(worker, typeOf<W>(), key, handler) | ||
|
Comment on lines
+211
to
+218
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't the API I'd ideally like to have, but since we don't have access to the full reflection library in this module, it's the best we can do. If we did, we could create the full worker type from the worker's class and the worker's However, while less flexible, it has the nice property that the type that is used to compare the worker will always be exactly the type for the worker that the IDE is showing you when you pass it to |
||
| } | ||
|
|
||
| /** | ||
| * Ensures [worker] is running. When the [Worker] emits an output, [handler] is called | ||
| * to determine the [WorkflowAction] to take. When the worker finishes, nothing happens (although | ||
| * another render pass may be triggered). | ||
| * | ||
| * @param workerType `typeOf<W>()` | ||
| * @param key An optional string key that is used to distinguish between identical [Worker]s. | ||
| */ | ||
| @OptIn(ExperimentalStdlibApi::class) | ||
| @PublishedApi | ||
| /* ktlint-disable parameter-list-wrapping */ | ||
| internal fun <T, PropsT, StateT, OutputT> | ||
| RenderContext<PropsT, StateT, OutputT>.runningWorker( | ||
| worker: Worker<T>, | ||
| workerType: KType, | ||
| key: String = "", | ||
| handler: (T) -> WorkflowAction<PropsT, StateT, OutputT> | ||
| ) { | ||
| /* ktlint-enable parameter-list-wrapping */ | ||
| val workerWorkflow = WorkerWorkflow<T>(workerType, key) | ||
| renderChild(workerWorkflow, props = worker, key = key, handler = handler) | ||
| } | ||
|
|
||
| /** | ||
| * Alternative to [RenderContext.actionSink] that allows externally defined | ||
| * event types to be mapped to anonymous [WorkflowAction]s. | ||
|
|
@@ -223,8 +262,8 @@ fun <EventT, PropsT, StateT, OutputT> RenderContext<PropsT, StateT, OutputT>.mak | |
| "Use runningWorker", | ||
| ReplaceWith("runningWorker(worker, key, handler)", "com.squareup.workflow.runningWorker") | ||
| ) | ||
| fun <PropsT, StateT, OutputT, T> RenderContext<PropsT, StateT, OutputT>.onWorkerOutput( | ||
| inline fun <PropsT, StateT, OutputT, reified T> RenderContext<PropsT, StateT, OutputT>.onWorkerOutput( | ||
| worker: Worker<T>, | ||
| key: String = "", | ||
| handler: (T) -> WorkflowAction<PropsT, StateT, OutputT> | ||
| noinline handler: (T) -> WorkflowAction<PropsT, StateT, OutputT> | ||
| ) = runningWorker(worker, key, handler) | ||
Uh oh!
There was an error while loading. Please reload this page.