FutureWidget<T> class

A Widget that builds depending on the state of one or more Futures.

This is similar to FutureBuilder but accepts separate callbacks for each state. Just like the built-in builders, the futureGen should not be created inside the build method because it would restart every time an ancestor is rebuilt.

It almost fully replaces the need for StreamBuilder in your application: when the instance of futureGen changes, the current state (data or error) is retained, and the onData and onError build callbacks offer isRefreshing (useful e.g. when adding a spinner next to an error or data, indicating a reload is happening). When the data is not loaded yet, the onLoading callback will be invoked. Also, it is possible to trigger a refresh with disposeState: true, which will invoke again onLoading.

If initialDataValue is provided, it is used in place of the data before one is available.

If the asynchronous operation completes with an error this builds onError. If onError is not provided reportError is called with the FlutterErrorDetails.

Example:

int num = 0;

class ExampleWidget extends StatefulWidget {
  const ExampleWidget({Key? key}) : super(key: key);

  @override
  ExampleWidgetState createState() => ExampleWidgetState();
}

class ExampleWidgetState extends State<ExampleWidget> {
  FutureContext<int> futureContext = FutureContext<int>(
      myFuture(false), RefreshType.nonPriorityDebounced, false);

  bool _isRefreshing = true;

  void _isRefreshingCallback(bool innerIsRefreshingValue) {
    setState(() {
      _isRefreshing = innerIsRefreshingValue;
    });
  }

  @override
  void initState() {
    super.initState();
  }

  static Future<int> myFuture(bool shouldThrow) async {
    await Future.delayed(const Duration(seconds: 4));
    if (shouldThrow) {
      throw Exception("You can't pass true as a param");
    }
    return num++;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        FutureWidget<int>(
          futureContext: futureContext,
          isRefreshingCallback: _isRefreshingCallback,
          onData: (context, data) =>
              Text('My data is: $data${_isRefreshing ? ' (REFRESHING)' : ''}'),
          onError: (context, error, stackTrace) {
            return Text(
              'Error was thrown: $error${_isRefreshing ? ' (REFRESHING)' : ''}',
            );
          },
          onLoading: (context) => const Text('Loading...'),
        ),
        ElevatedButton(
          onPressed: () {
            setState(() {
              futureContext = FutureContext<int>(
                  myFuture(false), RefreshType.priorityDebounced, false);
            });
          },
          child: const Text('increase num'),
        ),
        ElevatedButton(
          onPressed: () {
            setState(() {
              futureContext = FutureContext<int>(
                  myFuture(true), RefreshType.priorityUnfiltered, false);
            });
          },
          child: const Text('error'),
        ),
      ],
    );
  }
}
Inheritance

Constructors

FutureWidget({required FutureGen<T> futureGen, required DataBuilder<T> onData, required ErrorBuilder onError, required LoadingBuilder onLoading, required void isRefreshingCallback(bool isRefreshingState), bool keepAlive = false, Key? key})
Creates a widget that builds depending on the state of a FutureContext.
const
FutureWidget.initialData({required FutureGenWithInitialData<T> futureGen, required DataBuilder<T> onData, required ErrorBuilder onError, required WidgetBuilder onLoading, required void isRefreshingCallback(bool isRefreshingState), bool keepAlive = false, Key? key})
Creates a widget that builds depending on the state of a FutureContext.
const
FutureWidget.unsafeNoError({required FutureGen<T> futureGen, required DataBuilder<T> onData, required void isRefreshingCallback(bool isRefreshingState), required LoadingBuilder onLoading, bool keepAlive = false, Key? key})
Creates a widget that builds depending on the state of a FutureContext.
const
FutureWidget.unsafeOnlyData({required FutureGenWithInitialData<T> futureGen, required DataBuilder<T> onData, required void isRefreshingCallback(bool isRefreshingState), required WidgetBuilder onLoading, bool keepAlive = false, Key? key})
Creates a widget that builds depending on the state of a FutureContext.
const

Properties

futureGen AbstractFutureGen<T>
This is the object containing the future and the type of refresh that is listened to.
final
hashCode int
The hash code for this object.
no setterinherited
isRefreshingCallback → void Function(bool isRefreshingState)
This function lifts state up
final
keepAlive bool
Whether or not we should send a keep alive notification with AutomaticKeepAliveClientMixin.
final
key Key?
Controls how one widget replaces another widget in the tree.
finalinherited
onData → DataBuilder<T>
The default data builder.
final
onError → ErrorBuilder?
The builder that should be called when an error was thrown by the future in futureGen.
final
onLoadingWithFirstLoad → LoadingBuilder?
The builder that should be called when no data is available and no error was thrown by the future.
final
onLoadingWithoutFirstLoad WidgetBuilder?
The builder that should be called when no data is available and no error was thrown by the future.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

createElement() StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() State<StatefulWidget>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent 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 DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
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 ==(Object other) bool
The equality operator.
inherited