Migrating State Handle¶
state-handle from Arch Toolkit is superseded by event-observer-state in Arch Event Observer 2.3.0.
The new artifact is published with the Event Observer release. The old artifact only carries a POM
notice; there is no Maven relocation and no automatic dependency or import rewrite.
| Before | After |
|---|---|
io.github.matheus-corregiari:state-handle:2.0.0-rc17 |
io.github.matheus-corregiari:event-observer-state:3.0.0 |
br.com.arch.toolkit.stateHandle |
br.com.arch.toolkit.eventObserver.state |
Koin-provided Json |
Default Json, or an explicit argument |
| Native value with JSON shadow fallback | One JSON value per key |
SavableObject / Parcelable / Serializable markers |
@Serializable or explicit KSerializer<T> |
API changes¶
saveState<T>(),saveResponseState<T>(),value<T>(),get,set,flowandinvalidateretain their basic purpose.flow()now exposes stableStateFlowsnapshots.Tis a non-null payload type; a holder itself accepts null. Usevalue<String>(), notvalue<String?>(). Lists and maps can contain nullable values when their serializer supports them.saveResponseState(default = ...)takes a payload default. To deliver an actual operation result, callstate.set(dataResult). Defaults never replace restored values.- Direct holder constructors require a non-null serializer and no longer accept silent fallback
failure. The
json,scopeandstateHandleparameters remain explicit. loadalways starts another operation and returnsJob. The oldevaluateargument is removed; useif (state.get() == null) state.load { ... }for explicit reuse.set(value, distinct)remains available; observed state is also distinct..requiredand.defaultremain delegate fallbacks applied on reads and now agree with their observed flows. Assignments still persist the assigned value. Import them fromStateValue.Companion. Usedefault = valuefor persisted initialization orselect { it ?: fallback }for a derived fallback. Nullable states can still be cleared.- Use
bind,bindMappedandbindReducingfor plain flows; useload,loadMappedandloadReducingfor result flows. Useselectfor smaller states derived from one saved model. - Clearing uses a saved JSON null rather than removing the key. Do not remove an active key directly.
Worker execution¶
Producers, mappers, reducers and codecs now run on workerDispatcher, defaulting to
Dispatchers.Default. Capture saved values on the owner thread before starting a producer.
Callbacks handling plain operation errors still run on the owner scope. Custom serializers must
support worker use and immutable snapshots; do not mutate submitted or observed objects in place.
Tests can inject a dispatcher tied to their coroutine test scheduler through delegates or constructors.
setAsync prepares a direct write asynchronously. selectAsync retains the last completed projection.
Synchronous setters and projections remain available for small, cheap operations. See
performance limits.
Existing saved snapshots¶
The old native/shadow representation is not decoded by this module. Choose a new key (for example
users-v2) when adopting it, or explicitly convert old saved values before creating the new holder.
Do not reuse a key containing a native object as if it were JSON. Invalid content fails explicitly.
This does not change the Toolkit module's code or the behavior of consumers staying on the old artifact.
Restoration checklist¶
Use a handle provided by a restoring owner, serializable payloads and a main-thread scope. Restore
the payload as Success, reconnect continuous sources explicitly, and decide when to refresh.
Loading and errors are transient. savedStateHandleCompat() and enableSavedStateHandleCompat()
from the old README were not implemented APIs and are not provided here.
See the module guide for complete operation and platform semantics.
3.0.0: privately owned state¶
Version 3.0.0 publishes payload and result status from one immutable snapshot.
Public holder/delegate APIs and the saved JSON format stay compatible; existing JSON strings,
keys, Json configuration and explicit serializers need no conversion. Payload restoration
still produces Success for non-null data and None for null.
The behavioral change is ownership: an active holder no longer observes direct writes to its
SavedStateHandle key. Replace handle[key] = json with holder.set(payload) for small values
or holder.setAsync(payload) for expensive writes. Do not create two active holders or a raw
handle flow for the same key. Fallback/property delegates obey the same rule. Separate restored
owners/handles remain supported.
Async operations prepare a detached payload, JSON and deep comparisons on the worker, then save and publish on the owner. A collector can clear, replace or cancel synchronously without an older publication overwriting its status. Synchronous setters, restore and cheap selectors still execute on their caller. Default equality suppression is retained; equal payloads reuse the previous immutable value. Throwable identity determines whether an error is a new result.
This behavior changes in 3.0.0. No persistence guarantees are added for platforms without a restoring owner, and no automatic disk storage is introduced.