stated_result 0.2.0-preview.3 stated_result: ^0.2.0-preview.3 copied to clipboard
A bloc that accepts async source as input
stated_result #
A library built upon Bloc_Flutter and Provider to make it easy to support async operation
This library includes 4 sub-modules:
Multi-State Result #
The library includes 4 different types of MultiStateResult
, each has different state to indicates its internal state. The type is immutable data type, and can be pattern matched like enum.
ActionResult
: A result has 2 states:Completed
andFailed
. It can be used to represents the result of an action without return value.AsyncActionResult
: A result has 4 states:Pending
,Busy
,Completed
, andFailed
. It represents the full lifecycle of an async action without a return value.QueryResult<T>
: A result has 2 states:Succeeded
andFailed
, in whichSucceeded
would holds a value of given typeT
. It represents the result of a query that returns a certain type of data.AsyncQueryResult<T>
: A result has 4, states:Pending
,Busy
,Suceeded
, andFailed
. It represents a full lifecycle of a query that returns a certain type of data. Potentially, an extra stateDefault
can be used, it is likePending
indicates the query hasn't been started yet, but also holds avalue
likeSucceeded
. It can be used to indicates the scenario which app provides default value as optimistic updates.
How it works #
Typically, the result can be used to represent the result of an async operation, such as calling API or loading data from DB, or time consuming data processing.
Typically, the result itself should be AsyncActionResult
or AsyncQueryResult
, depends on whether app cares about the return value or not, and UI would renders accordingly, such as loading screen
error screen
or the successful screen
.
The query/action itself, would be represented as Future<QueryResult>
/Future<ActionResult>
, which can be used to update AsyncQueryResult
and AsyncActionResult
accordingly.
Typically, AsyncActionResult
would be holds by a Bloc
or ValueNotifier
, which will be discussed below.
Convert Sync Result to Async Result #
asAsyncResult
can convert sync result into its async counterpart accordingly.
AsyncActionResult asyncActionResult = actionResult.asAsyncResult();
AsyncQueryResult asyncQueryResult = queryResult.asAsyncResult();
Convert Future Types #
Future.asActionResult
can materialise any future into Future<ActionResult>
. The new future would always fulfills, when original future failed, it captures the error into a FailedResult
accordingly.
Future<ActionResult>.asActionResult
would flatten the hierarchy and respect the failed value from original future.
Future<T>.asQueryResult
would matertialse the future of T
into Future<QueryResult<T>>
. The new future would always fulfills, when original future failed, it captures the error into a FailedResult
accordingly.
Multi-State Result Builder #
MultiStateResult
types provide map
and/or mapOr
method to pattern match and map the value, which can be used to build UI manually.
ActionResultBuilder
and QueryResultBuilder
#
In practise, ActionResultBuilder
and QueryResultBuilder
provided by this library can be more convenient, with a few extra features.
ActionResultBuilder
and QueryResultBuilder
accepts different builder function to build the UI according to the state of the AsyncActionResult
or the AsyncQueryResult
.
An simple example:
Widget build(BuildContext context, AsyncActionResult result) =>
ActionResultBuilder(
result: result,
pendingBuilder: (_context) => Center(child: Text("No Data")),
busyBuilder: (_context) => Center(child: CircularProgressIndicator()),
failedBuilder: (_context, error, _stackTrace) => Center(
child: Text("Error: $error"),
),
completedBuilder: (_context) => Center(child: Text("Completed")),
);
Non critical state default builders #
For ActionResultBuilder
and QueryResultBuilder
, completed
and succeeded
are considered as critical builder, which is mandatory each time to instantiate the Widget. While pendingBuilder
, busyBuilder
, and failedBuilder
are optional, which can be omitted.
When the given builder is omitted, the ResultBuilder
would search the widget hierarchy to find any default builder has been given. Just like Text
would search DefaultTextStyle
if textStyle
is not explicitly given.
Accordingly, DefaultPendingResultBuilder
, DefaultBusyResultBuilder
, and DefaultFailedResultBuilder
can be used to provide those default builders to their children along the widget tree.
DefaultResultBuilder #
If more than one default builder needs to be configured, rather than nested DefaultXXXResultBuilder
, which results a relatively ugly code, DefaultResultBuilder
can be used, which allow to configure multiple default builders at once.
DefaultResultBuilder
can be use to setup the unified UI style of a portion of the screen.
Global default builders #
If optional builders are omitted, and no default builder are given. The ResultBuilder
widget would uses something called global default builder
to render the UI.
Which can be setup via
DefaultPendingResultBuilder.globalBuilder
DefaultBusyResultBuilder.globalBuilder
DefaultFailedResultBuilder.globalBuilder
It also can be configured in batch via DefaultResultBuilder.setGlobalBuilder
Bloc Integration #
Library provided the classes to integrate the [MultiStateResult] to Bloc
This library uses Cubit
instead of Bloc
, which is a simplified and easier-to-use Bloc
.
ActionCubit
: ACubit
holdsAsyncActionResult
, it also provides protected methods to update its value from different kinds ofFuture
QueryCubit<T>
: ACubit
holdsAsyncQueryResult<T>
, it also provides protected methods to update its value from different kinds ofFuture
Both ActionCubit
and QueryCubit
can be provided into widget tree via BlocProvider
Bloc Builder and Bloc Consumer #
Like BlocBuilder
and BlocConsumer
provided by Bloc_Flutter library, the following types are provided:
ActionBlocBuilder
:BlocBuilder
that consumesActionCubit
viaActionResultBuilder
ActionBlocConsumer
:BlocConsumer
that consumesActionCubit
viaActionResultBuilder
QueryBlocBuilder
:BlocBuilder
that consumesQueryCubit
viaQueryResultBuilder
QueryBlocConsumer
:BlocConsumer
that consumesQueryCubit
viaQueryResultBuilder
ValueNotifier Integration #
Besides of Bloc, this library also provides the integration to ValueNotifier
and ListenableBuilder
.
ActionNotifier
: AValueNotifier
holdsAsyncActionResult
, it also provides protected methods to update its value from different kinds ofFuture
QueryNotifier<T>
: AValueNotifier
holdsAsyncQueryResult<T>
, it also provides protected methods to update its value from different kinds ofFuture
Listenable Builder #
Like `ListenableBuilder, the following classes are provided:
ActionListenableBuilder
:ListenableBuilder
that consumesActionNotifier
viaActionResultBuilder
QueryListenableBuilder
:ListenableBuilder
that consumesQueryNotifier
viaQueryResultBuilder