A sealed union representing the lifecycle states of an asynchronous operation.
AsyncState is commonly wrapped by AsyncSignal or returned by asynchronous
computed signals (computedAsync, computedFrom) to model loading, success (data),
and error outcomes.
State Hierarchy#
The states are modeled as a robust hierarchy of immutable types:
- AsyncLoading: Pure loading state with no pre-existing data.
-
AsyncData: Success state holding a resolved value of type
T.- AsyncDataRefreshing: Refreshing in the background (holding historical data).
- AsyncDataReloading: Reloading (holding historical data).
-
AsyncError: Failure state holding an error and optional stack trace.
- AsyncErrorRefreshing: Refreshing in the background (holding historical error).
- AsyncErrorReloading: Reloading (holding historical error).
Pattern Matching & Switch Expressions#
Standard Dart switch expressions provide type-safe branching across all states:
Important
Branch Matching Order & Existing Value Preservation:
Since reloading and refreshing states (e.g., AsyncDataRefreshing, AsyncDataReloading) implement both
AsyncData and AsyncLoading, matching on AsyncLoading first
will prematurely swallow existing data!
Always place AsyncData and AsyncError branches before
AsyncLoading to ensure pre-existing data or error states are successfully rendered during refreshes:
final value = switch (state) {
AsyncDataRefreshing<int> r => 'Refreshing with value: ${r.value}',
AsyncDataReloading<int> r => 'Reloading with value: ${r.value}',
AsyncData<int> data => 'Stable value: ${data.value}',
AsyncErrorRefreshing<int> r => 'Refreshing error: ${r.error}',
AsyncErrorReloading<int> r => 'Reloading error: ${r.error}',
AsyncError<int> error => 'Stable error: ${error.error}',
AsyncLoading<int>() => 'Pure Loading State (no prior data)',
};
Standard Branching Methods (map and maybeMap)#
If you prefer standard callbacks over switch expressions, use map or maybeMap:
state.map(
data: (value) => 'Value: $value',
error: (error, stackTrace) => 'Error: $error',
loading: () => 'Loading...',
);
Constructors#
View Constructors
AsyncState()
AsyncState.dataReloading(T data)
Create a state with a value that is reloading
AsyncState.dataRefreshing(T data)
Create a state with a value that is refreshing
AsyncState.data(T data)
Create a state with a value
AsyncState.errorReloading(Object error, [StackTrace? stackTrace])
Create a state with an error that is reloading
AsyncState.errorRefreshing(Object error, [StackTrace? stackTrace])
Create a state with an error that is refreshing
AsyncState.error(Object error, [StackTrace? stackTrace])
Create a state with an error
AsyncState.loading()
Create a loading state
Methods#
View Methods
bool hasValue
Returns true if the state has a value
bool hasError
Returns true if the state has an error
bool isLoading
Check if the state is a loading state
bool isRefreshing
Returns true if the state is refreshing with a loading flag, has a value or error and is not the loading state
bool isReloading
Returns true if the state is reloading with having a value or error, and is the loading state
T requireValue
Force unwrap the value of the state.
This will throw an error if the state does not have a value.
T? value
Returns the value of the state.
Object? error
Returns the error of the state.
StackTrace? stackTrace
Returns the stack trace of the state.
E map({required AsyncDataBuilder<E, T> data, required AsyncErrorBuilder<E> error, required AsyncStateBuilder<E> loading, AsyncStateBuilder<E>? reloading, AsyncStateBuilder<E>? refreshing})
Map the state to a value.
final signal = StreamSignal<int>();
signal.value.map(
data: (value) => 'Value: $value',
error: (error, stackTrace) => 'Error: $error',
loading: () => 'Loading...',
);
The error Function below can be one of two types:
- (dynamic) -> FutureOr
- (dynamic, StackTrace) -> FutureOr
E maybeMap({AsyncDataBuilder<E, T>? data, AsyncErrorBuilder<E>? error, AsyncStateBuilder<E>? loading, AsyncStateBuilder<E>? reloading, AsyncStateBuilder<E>? refreshing, required AsyncStateBuilder<E> orElse})
Map the state to a value with optional or else.
final signal = StreamSignal<int>();
signal.value.maybeMap(
data: (value) => 'Value: $value',
orElse: () => 'Loading...',
);
The error Function below can be one of two types:
- (dynamic) -> FutureOr
- (dynamic, StackTrace) -> FutureOr
bool ==(covariant AsyncState<T> other)
int hashCode
AsyncErrorRefreshing#
A loading state with an error. Signal the query conditions that led to the error has remained the same and is being refreshed.
Constructors#
View Constructors
AsyncErrorRefreshing(super.error, super.stackTrace)
Create a state with an error that is refreshing
Methods#
AsyncDataRefreshing#
A loading state with a value. Signals the query conditions that led to the data has remained the same and is being refreshed
Constructors#
Methods#
AsyncErrorReloading#
A loading state with an error. Signal the query conditions that led to the error has changed and is being reloaded.
Constructors#
View Constructors
AsyncErrorReloading(super.error, super.stackTrace)
Create a state with an error that is reloading
Methods#
AsyncDataReloading#
A loading state with a value. Signals the query conditions that led to the data has changed and is being reloaded.
Constructors#
Methods#
AsyncLoading#
State for an AsyncState with a loading state
Constructors#
Methods#
View Methods
bool hasValue
bool hasError
T? value
bool isLoading
bool isRefreshing
bool isReloading
T requireValue
Object? error
StackTrace? stackTrace
bool ==(covariant AsyncState other)
int hashCode
AsyncError#
State for an AsyncState with an error
Constructors#
Properties#
Methods#
View Methods
bool hasValue
bool hasError
T? value
bool isLoading
bool isRefreshing
bool isReloading
T requireValue
bool ==(covariant AsyncState other)
int hashCode
AsyncData#
State for an AsyncState with a value