Store
A construct for managing complex state safely in concurrent environments.
Receives Actions via dispatch which contain information about the outside world.
Allows tracking the execution state of Effects with trackedEffect and trackedFlowEffect.
An Effect can have an owner. This allows to relate an effect to something else. E.g. this might be UI that wants to display a loading state for an effect as long as it's running, and display the result when it's done.
An owner can cease to exist while the Effect is running, reappear at a later time, and then handle the result of its effect. The Store does not have references to the owners of effects, which allows for owners to disappear and reappear without having to handle references as with Listeners. This eases handling scenarios like Activity deaths on Android, where the UI that triggered an action can disappear completely - Objects garbage collected - and reappear at a later time wanting to display the current state of the action. The screen can be set as owner using a persistent id and a new/resurrected instance can find the data again by that ownerId.
Because the Store doesn't know anything about effect owners, it can't clean up effect results of effects with owners by itself, as it doesn't know when an owner has handled a result. The potential "disappearance" of an owner does not imply that an effect state is not needed anymore, as it might reappear later. Therefore, to clean up an EffectState and free the memory, an owner has to do so explicitly by removing it via an Action.
If an owner does not remove its EffectState from the effect states, then it will stay there indefinitely, using up memory. Ergo when an owner ceases to exist completely and does not reappear, then its effect states continue to exist. This is a known - and currently accepted - limitation of this approach.
Why are ownerIds needed, when effectIds exist? An owner dispatches an action to trigger an effect. This action lands in a queue and is processed a bit later. Only then is the effectId created. If the owner disappeared before, then it can't know the effectId of the effect it triggered. By passing an ownerId with the action, the id can be passed to the effect. Even if the owner disappeared in the meantime, it can later identify its effects by the ownerId.
The Reducer is run atomically, meaning state updates are thread-safe.
Parameters
The initial state of the Store.
The CoroutineDispatcher all operations run on. Reducer, effects, and internal operations run on this dispatcher. Default value is Dispatchers.Default.
The name for the CoroutineScope the Store uses. Useful for debugging. The default is DEFAULT_COROUTINE_SCOPE_NAME.
A logger that logs received actions and state updates. Useful for debugging. The default is NoopLogger.
The ExceptionHandler that is installed in the CoroutineScope of the Store. All uncaught exceptions occurring in the reducer and effects are passed to this handler. The default is ThrowingExceptionHandler which rethrows all received exceptions.