FutureBuilder< T> class
Widget that builds itself based on the latest snapshot of interaction with a Future.
The future must have been obtained earlier, e.g. during State.initState,
State.didUpdateConfig
, or State.didChangeDependencies. It must not be
created during the State.build or StatelessWidget.build method call when
constructing the FutureBuilder. If the future is created at the same
time as the FutureBuilder, then every time the FutureBuilder's parent is
rebuilt, the asynchronous task will be restarted.
A general guideline is to assume that every build
method could get called
every frame, and to treat omitted calls as an optimization.
Timing
Widget rebuilding is scheduled by the completion of the future, using State.setState, but is otherwise decoupled from the timing of the future. The builder callback is called at the discretion of the Flutter pipeline, and will thus receive a timing-dependent sub-sequence of the snapshots that represent the interaction with the future.
A side-effect of this is that providing a new but already-completed future to a FutureBuilder will result in a single frame in the ConnectionState.waiting state. This is because there is no way to synchronously determine that a Future has already completed.
Builder contract
For a future that completes successfully with data, assuming initialData is null, the builder will be called with either both or only the latter of the following snapshots:
new AsyncSnapshot<String>.withData(ConnectionState.waiting, null)
new AsyncSnapshot<String>.withData(ConnectionState.done, 'some data')
If that same future instead completed with an error, the builder would be called with either both or only the latter of:
new AsyncSnapshot<String>.withData(ConnectionState.waiting, null)
new AsyncSnapshot<String>.withError(ConnectionState.done, 'some error')
The initial snapshot data can be controlled by specifying initialData. You would use this facility to ensure that if the builder is invoked before the future completes, the snapshot carries data of your choice rather than the default null value.
The data and error fields of the snapshot change only as the connection
state field transitions from waiting
to done
, and they will be retained
when changing the FutureBuilder configuration to another future. If the
old future has already completed successfully with data as above, changing
configuration to a new future results in snapshot pairs of the form:
new AsyncSnapshot<String>.withData(ConnectionState.none, 'data of first future')
new AsyncSnapshot<String>.withData(ConnectionState.waiting, 'data of second future')
In general, the latter will be produced only when the new future is non-null, and the former only when the old future is non-null.
A FutureBuilder behaves identically to a StreamBuilder configured with
future?.asStream()
, except that snapshots with ConnectionState.active
may appear for the latter, depending on how the stream is implemented.
_calculation
field is set by pressing a button elsewhere in the UI.
FutureBuilder<String>(
future: _calculation, // a previously-obtained Future<String> or null
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return Text('Awaiting result...');
case ConnectionState.done:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
return Text('Result: ${snapshot.data}');
}
return null; // unreachable
},
)
- Inheritance
- Object
- Diagnosticable
- DiagnosticableTree
- Widget
- StatefulWidget
- FutureBuilder
Constructors
-
FutureBuilder({Key key, Future<
T> future, T initialData, @required AsyncWidgetBuilder< T> builder }) -
Creates a widget that builds itself based on the latest snapshot of
interaction with a Future. [...]
const
Properties
-
builder
→ AsyncWidgetBuilder<
T> -
The build strategy currently used by this builder. [...]
final
-
future
→ Future<
T> -
The asynchronous computation to which this builder is currently connected,
possibly null. [...]
final
- initialData → T
-
The data that will be used to create the snapshots provided until a
non-null future has completed. [...]
final
- hashCode → int
-
The hash code for this object. [...]
read-only, inherited
- key → Key
-
Controls how one widget replaces another widget in the tree. [...]
final, inherited
- runtimeType → Type
-
A representation of the runtime type of the object.
read-only, inherited
Methods
-
createState(
) → State< FutureBuilder< T>> -
Creates the mutable state for this widget at a given location in the tree. [...]
override
-
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree. [...]
inherited
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children. [...]
@protected, inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node. [...]
inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a non-existent method or property is accessed. [...]
inherited
-
toDiagnosticsNode(
{String name, DiagnosticsTreeStyle style }) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by toStringDeep. [...]
inherited
-
toString(
{DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String -
Returns a string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne: '', String prefixOtherLines, DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String -
Returns a string representation of this node and its descendants. [...]
inherited
-
toStringShallow(
{String joiner: ', ', DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String -
Returns a one-line detailed description of the object. [...]
inherited
-
toStringShort(
) → String -
A short, textual description of this widget.
inherited
Operators
-
operator ==(
dynamic other) → bool -
The equality operator. [...]
inherited