import 'dart:async'; import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; // ignore: directives_ordering import 'package:fis_lib_qrcode/qr_flutter.dart'; import 'package:fis_ui/index.dart'; class CustomFutureBuilder extends StatefulWidget implements FWidget { /// Creates a widget that builds itself based on the latest snapshot of /// interaction with a [Future]. /// /// The [builder] must not be null. const CustomFutureBuilder({ Key? key, this.future, this.initialData, required this.builder, }) : assert(builder != null), super(key: key); final Future? future; final AsyncWidgetBuilder builder; final T? initialData; static bool debugRethrowError = false; @override State> createState() => _CustomFutureBuilderState(); } class _CustomFutureBuilderState extends State> { /// An object that identifies the currently active callbacks. Used to avoid /// calling setState from stale callbacks, e.g. after disposal of this state, /// or after widget reconfiguration to a new Future. Object? _activeCallbackIdentity; late AsyncSnapshot _snapshot; @override void initState() { super.initState(); _snapshot = widget.initialData == null ? AsyncSnapshot.nothing() : AsyncSnapshot.withData( ConnectionState.none, widget.initialData as T); _subscribe(); } @override void didUpdateWidget(CustomFutureBuilder oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.future != widget.future) { if (_activeCallbackIdentity != null) { _unsubscribe(); _snapshot = _snapshot.inState(ConnectionState.none); } _subscribe(); } } @override Widget build(BuildContext context) => widget.builder(context, _snapshot); @override void dispose() { _unsubscribe(); super.dispose(); } void _subscribe() { if (widget.future != null) { final Object callbackIdentity = Object(); _activeCallbackIdentity = callbackIdentity; widget.future!.then((T data) { if (_activeCallbackIdentity == callbackIdentity) { setState(() { _snapshot = AsyncSnapshot.withData(ConnectionState.done, data); }); } }, onError: (Object error, StackTrace stackTrace) { if (_activeCallbackIdentity == callbackIdentity) { setState(() { _snapshot = AsyncSnapshot.withError( ConnectionState.done, error, stackTrace); }); } assert(() { if (FutureBuilder.debugRethrowError) { Future.error(error, stackTrace); } return true; }()); }); _snapshot = _snapshot.inState(ConnectionState.waiting); } } void _unsubscribe() { _activeCallbackIdentity = null; } }