custom_qrcode_builder.dart 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import 'dart:async';
  2. import 'dart:ui' as ui;
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/services.dart';
  5. // ignore: directives_ordering
  6. import 'package:fis_lib_qrcode/qr_flutter.dart';
  7. import 'package:fis_ui/index.dart';
  8. class CustomFutureBuilder<T> extends StatefulWidget implements FWidget {
  9. /// Creates a widget that builds itself based on the latest snapshot of
  10. /// interaction with a [Future].
  11. ///
  12. /// The [builder] must not be null.
  13. const CustomFutureBuilder({
  14. Key? key,
  15. this.future,
  16. this.initialData,
  17. required this.builder,
  18. }) : assert(builder != null),
  19. super(key: key);
  20. final Future<T>? future;
  21. final AsyncWidgetBuilder<T> builder;
  22. final T? initialData;
  23. static bool debugRethrowError = false;
  24. @override
  25. State<CustomFutureBuilder<T>> createState() => _CustomFutureBuilderState<T>();
  26. }
  27. class _CustomFutureBuilderState<T> extends State<CustomFutureBuilder<T>> {
  28. /// An object that identifies the currently active callbacks. Used to avoid
  29. /// calling setState from stale callbacks, e.g. after disposal of this state,
  30. /// or after widget reconfiguration to a new Future.
  31. Object? _activeCallbackIdentity;
  32. late AsyncSnapshot<T> _snapshot;
  33. @override
  34. void initState() {
  35. super.initState();
  36. _snapshot = widget.initialData == null
  37. ? AsyncSnapshot<T>.nothing()
  38. : AsyncSnapshot<T>.withData(
  39. ConnectionState.none, widget.initialData as T);
  40. _subscribe();
  41. }
  42. @override
  43. void didUpdateWidget(CustomFutureBuilder<T> oldWidget) {
  44. super.didUpdateWidget(oldWidget);
  45. if (oldWidget.future != widget.future) {
  46. if (_activeCallbackIdentity != null) {
  47. _unsubscribe();
  48. _snapshot = _snapshot.inState(ConnectionState.none);
  49. }
  50. _subscribe();
  51. }
  52. }
  53. @override
  54. Widget build(BuildContext context) => widget.builder(context, _snapshot);
  55. @override
  56. void dispose() {
  57. _unsubscribe();
  58. super.dispose();
  59. }
  60. void _subscribe() {
  61. if (widget.future != null) {
  62. final Object callbackIdentity = Object();
  63. _activeCallbackIdentity = callbackIdentity;
  64. widget.future!.then<void>((T data) {
  65. if (_activeCallbackIdentity == callbackIdentity) {
  66. setState(() {
  67. _snapshot = AsyncSnapshot<T>.withData(ConnectionState.done, data);
  68. });
  69. }
  70. }, onError: (Object error, StackTrace stackTrace) {
  71. if (_activeCallbackIdentity == callbackIdentity) {
  72. setState(() {
  73. _snapshot = AsyncSnapshot<T>.withError(
  74. ConnectionState.done, error, stackTrace);
  75. });
  76. }
  77. assert(() {
  78. if (FutureBuilder.debugRethrowError) {
  79. Future<Object>.error(error, stackTrace);
  80. }
  81. return true;
  82. }());
  83. });
  84. _snapshot = _snapshot.inState(ConnectionState.waiting);
  85. }
  86. }
  87. void _unsubscribe() {
  88. _activeCallbackIdentity = null;
  89. }
  90. }