LocalClosureContainer

A DispatchClosure.Element, that handles local changes of a DispatchClosure.

Generally, this mechanism is not required to know in normal usage. However, it might be useful to introduce some new special mechanisms to the store.

LocalClosureContainer has following properties:

  • It doesn't affect the closure that is a part of. Therefore, it must be accessed directly by DispatchClosure.local` to receive locally changed values. Original closure always remains the same.

  • It works only for a time of dispatch call. Therefore, accessing it outside of dispatch function returns unchanged values.

  • It's hierarchical. Nested dispatch calls receive accumulated local closures.

  • Every change is identified by Slot.

These properties are not only determined by the implementation of this interface, but also by the convention. Therefore, it is important to use this mechanism according to the documentation and attached examples. Any local change should occur through withLocalClosure. Manual slots manipulation it's not recommended.

Interactions with a store

By default, store contains an instance of LocalClosureContainer (created by LocalClosureContainer()). It applies changes to the original closure field, so accessing local closure without local changes, returns values from the original one. Because local changes remains only for a time of dispatch call, accessing them from coroutines launched by a middleware, doesn't work.

Example

How to perform DispatchClosure change:

fun DispatchScope<*>.customDispatch(action: Action) {
withLocalClosure(ClosureElement()) {
dispatch(SomeAction)
}
}

How to access changed values:

fun customMiddleware(): Middleware<AppState> = {
var element = closure.local[ClosureElement] // outside of dispatch - returns values from the original closure
dispatchFunction {
element = closure.local[ClosureElement] // direct access to local closure in dispatch
// properly returns local changes

element = closure.local[ClosureElement] // direct access to original closure
// returns values from the original closure
}
}

Types

Link copied to clipboard
class Frame

Identifies a single hierarchy of local changes.

Link copied to clipboard
Link copied to clipboard
class Slot

Identifies single local change.

Functions

Link copied to clipboard
abstract fun applyTo(closure: DispatchClosure): DispatchClosure

Returns closure with local changes applied.

Link copied to clipboard
open override fun <T : DispatchClosure.Element> find(key: DispatchClosure.Key<T>): T?

Returns Element associated with the key or null.

Link copied to clipboard
open operator override fun <T : DispatchClosure.Element> get(key: DispatchClosure.Key<T>): T

Returns Element associated with the key or throws MissingClosureElementException.

Link copied to clipboard
open operator override fun minus(key: DispatchClosure.Key<*>): DispatchClosure

Returns a closure without the element with a given key

Link copied to clipboard
open operator fun plus(closure: DispatchClosure): DispatchClosure

Combines this closure with incoming closure. If both closures contain elements with the same keys, the ones from the incoming closure remain.

Link copied to clipboard

Registers a new frame that creates a new hierarchy of local changes.

Link copied to clipboard

Registers local change of a closure.

Link copied to clipboard

Removes a frame along with local changes that occurred.

Link copied to clipboard

Undo local change associated with a slot

Link copied to clipboard

Returns elements form this DispatchClosure as a Map.

Properties

Link copied to clipboard
open override val key: LocalClosureContainer.Key

Key of this element.

Inheritors

Link copied to clipboard

Extensions

Link copied to clipboard
Link copied to clipboard
fun DispatchClosure.launchForeground(context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit): Job

Launches a foreground job using this closure. By default, it's launched in a scope provided by DispatchCoroutineScope. This behaviour might be changed by dispatchJobIn or joinDispatchJob. Because this function uses local closure, calling it outside dispatch should not be done, because it might result in unexpected behaviour.

Link copied to clipboard

Returns this closure with local changes.

Link copied to clipboard
inline fun DispatchClosure.registeringJob(closure: DispatchClosure = EmptyDispatchClosure, newFrame: Boolean = false, block: DispatchClosure.() -> Unit): Job

Runs block that must register a foreground job. It adds SingleForegroundJobRegistry to local closure to allow proper job registration. Local closure change creates a new frame if newFrame is true.

Link copied to clipboard
inline fun <T> DispatchClosure.withLocalClosure(closure: DispatchClosure, newFrame: Boolean = false, block: DispatchClosure.() -> T): T

Changes LocalClosureContainer with a given closure for a time of block execution.