import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'log.dart'; typedef WidgetBuilder = Widget Function(BuildContext context, T snapshot); class FutureLoadingBuilder extends StatefulWidget { const FutureLoadingBuilder({ Key key, @required this.future, this.initialData, @required this.builder, this.mutable = false, this.loadingIndicator, }) : assert(builder != null), super(key: key); /// The asynchronous computation to which this builder is currently connected, /// possibly null. /// /// If no future has yet completed, including in the case where [future] is /// null, the data provided to the [builder] will be set to [initialData]. final Future future; final WidgetBuilder builder; /// The data that will be used to create the snapshots provided until a /// non-null [future] has completed. /// /// If the future completes with an error, the data in the [AsyncSnapshot] /// provided to the [builder] will become null, regardless of [initialData]. /// (The error itself will be available in [AsyncSnapshot.error], and /// [AsyncSnapshot.hasError] will be true.) final T initialData; /// default is true /// /// set to false if the future will change. final bool mutable; final Widget loadingIndicator; @override _FutureLoadingBuilderState createState() => _FutureLoadingBuilderState(); } class _FutureLoadingBuilderState extends State> { Future future; @override void initState() { super.initState(); future = widget.future; } @override Widget build(BuildContext context) { return FutureBuilder( future: widget.mutable ? widget.future : future, initialData: widget.initialData, builder: (BuildContext context, AsyncSnapshot snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: case ConnectionState.active: case ConnectionState.waiting: return widget.loadingIndicator ?? Center(child: CircularProgressIndicator()); case ConnectionState.done: if (snapshot.hasError) { var error = snapshot.error; if (error is SocketException) { d('SocketException-> ${error.message}'); return Center( child: Text( 'Please check your connection', overflow: TextOverflow.fade, ), ); } else if (error is PlatformException && error.code == 'ERROR_GEOCODING_COORDINATES') { return Text( 'Please check your connection', overflow: TextOverflow.fade, ); } else { d('Unknow error: $error'); return Center(child: Text('Unknown error')); } } return widget.builder(context, snapshot.data); } return widget.builder(context, snapshot.data); }, ); } }