diff --git a/CHANGELOG.md b/CHANGELOG.md index 4435e1a..c8cad8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ +## 5.1.0 +September 20, 2024 +- catchAsyncError() for mixin FutureBuilderStateMixin + ## 5.0.0+3 September 04, 2024 - Remove all deprecated properties, functions, and methods diff --git a/example/lib/src/controller/app/app_controller.dart b/example/lib/src/controller/app/app_controller.dart index 9dbec29..36ca2d4 100644 --- a/example/lib/src/controller/app/app_controller.dart +++ b/example/lib/src/controller/app/app_controller.dart @@ -25,9 +25,8 @@ class ExampleAppController extends StateXController with EventsControllerMixin { }); } - /// Supply an 'error handler' routine if something goes wrong - /// in the corresponding initAsync() routine. - /// Returns true if the error was properly handled. + /// The initAsync() function has failed and a 'error' widget will be displayed.' + /// This takes in the snapshot.error details. @override void onAsyncError(FlutterErrorDetails details) {} diff --git a/example/lib/src/controller/home/controller.dart b/example/lib/src/controller/home/controller.dart index eaf5a18..283fb8d 100644 --- a/example/lib/src/controller/home/controller.dart +++ b/example/lib/src/controller/home/controller.dart @@ -63,14 +63,4 @@ class Controller extends StateXController with EventsControllerMixin { dataObject = _model.sayHello(); } } - - /// ************** Life cycle events **************** - /// - /// - - @override - Future initAsync() async { - // Return false to test such a circumstance - return !ExampleAppController().allowErrors; - } } diff --git a/example/lib/src/view/app/my_app.dart b/example/lib/src/view/app/my_app.dart index 69bd9b1..2410e49 100644 --- a/example/lib/src/view/app/my_app.dart +++ b/example/lib/src/view/app/my_app.dart @@ -31,6 +31,7 @@ class _MyAppState extends AppStateX with ClassNameMixin { /// Demonstrate passing an 'object' down the Widget tree much like /// how it's done using Scoped Model, but better. object: 'Hello!', + showBinding: true, // Print event function calls ); @override diff --git a/example/lib/src/view/home/page_01.dart b/example/lib/src/view/home/page_01.dart index 75fa500..f2fb922 100644 --- a/example/lib/src/view/home/page_01.dart +++ b/example/lib/src/view/home/page_01.dart @@ -6,8 +6,6 @@ import '/src/controller.dart'; import '/src/view.dart'; -import 'run_state_mixins.dart'; - /// The first page displayed in this app. class Page1 extends StatefulWidget { /// Page 1 @@ -111,7 +109,6 @@ class Page1State extends StateX with EventsStateMixin { body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const RunFutureBuilderStateMixin(), // Merely for testing _timer.wordPair, const Flexible( child: Padding( diff --git a/example/lib/src/view/home/page_02.dart b/example/lib/src/view/home/page_02.dart index 96485e5..c0322c7 100644 --- a/example/lib/src/view/home/page_02.dart +++ b/example/lib/src/view/home/page_02.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:example/src/view/home/run_state_mixins.dart'; + import '/src/controller.dart'; import '/src/view.dart'; diff --git a/example/lib/src/view/home/run_state_mixins.dart b/example/lib/src/view/home/run_state_mixins.dart index 6b89adc..98ab043 100644 --- a/example/lib/src/view/home/run_state_mixins.dart +++ b/example/lib/src/view/home/run_state_mixins.dart @@ -10,20 +10,24 @@ class RunFutureBuilderStateMixin extends StatefulWidget { const RunFutureBuilderStateMixin({super.key}); @override - State createState() => _State(); + State createState() => _TestState(); } /// Calling the 'default' functions without a subclass. -class _State extends State with FutureBuilderStateMixin { +class _TestState extends StateX { + _TestState() : super(useInherited: true); @override void initState() { super.initState(); initAsync(); + stateSet(null); } @override Widget build(BuildContext context) { buildF(context); + builder(context); + dependOnInheritedWidget(context); return const SizedBox.shrink(); } } diff --git a/lib/part01_statex.dart b/lib/part01_statex.dart index 33fcd0b..2b3225a 100644 --- a/lib/part01_statex.dart +++ b/lib/part01_statex.dart @@ -226,8 +226,7 @@ abstract class StateX extends State assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: initAsync() in $this'); + debugPrint('============ Event: initAsync() in $this'); } return true; }()); @@ -282,8 +281,7 @@ abstract class StateX extends State assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: initState() in $this'); + debugPrint('============ Event: initState() in $this'); } return true; }()); @@ -315,8 +313,7 @@ abstract class StateX extends State assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didChangeDependencies() in $this'); + debugPrint('============ Event: didChangeDependencies() in $this'); } return true; }()); @@ -372,8 +369,7 @@ abstract class StateX extends State assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: activate() in $this'); + debugPrint('============ Event: activate() in $this'); } return true; }()); @@ -418,8 +414,7 @@ abstract class StateX extends State // // assert(() { // if (kDebugMode) { -// //ignore: avoid_print -// print('============ _copyOverState(): $this copied $oldStateX'); +// debugPrint('============ _copyOverState(): $this copied $oldStateX'); // } // return true; // }()); @@ -485,8 +480,7 @@ abstract class StateX extends State assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: deactivate() in $this'); + debugPrint('============ Event: deactivate() in $this'); } return true; }()); @@ -528,8 +522,7 @@ abstract class StateX extends State assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: dispose() in $this'); + debugPrint('============ Event: dispose() in $this'); } return true; }()); @@ -566,8 +559,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didUpdateWidget() in $this'); + debugPrint('============ Event: didUpdateWidget() in $this'); } return true; }()); @@ -756,8 +748,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didRequestAppExit() in $this'); + debugPrint('============ Event: didRequestAppExit() in $this'); } return true; }()); @@ -815,8 +806,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didPopRoute() in $this'); + debugPrint('============ Event: didPopRoute() in $this'); } return true; }()); @@ -866,8 +856,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didPushRouteInformation() in $this'); + debugPrint('============ Event: didPushRouteInformation() in $this'); } return true; }()); @@ -905,8 +894,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didPopNext() in $this'); + debugPrint('============ Event: didPopNext() in $this'); } return true; }()); @@ -942,8 +930,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didPush() in $this'); + debugPrint('============ Event: didPush() in $this'); } return true; }()); @@ -979,8 +966,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didPop() in $this'); + debugPrint('============ Event: didPop() in $this'); } return true; }()); @@ -1016,8 +1002,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didPushNext() in $this'); + debugPrint('============ Event: didPushNext() in $this'); } return true; }()); @@ -1073,8 +1058,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didChangeMetrics() in $this'); + debugPrint('============ Event: didChangeMetrics() in $this'); } return true; }()); @@ -1125,8 +1109,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didChangeTextScaleFactor() in $this'); + debugPrint('============ Event: didChangeTextScaleFactor() in $this'); } return true; }()); @@ -1165,8 +1148,8 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didChangePlatformBrightness() in $this'); + debugPrint( + '============ Event: didChangePlatformBrightness() in $this'); } return true; }()); @@ -1210,8 +1193,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didChangeLocales() in $this'); + debugPrint('============ Event: didChangeLocales() in $this'); } return true; }()); @@ -1254,8 +1236,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didHaveMemoryPressure() in $this'); + debugPrint('============ Event: didHaveMemoryPressure() in $this'); } return true; }()); @@ -1297,8 +1278,8 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: didChangeAccessibilityFeatures() in $this'); + debugPrint( + '============ Event: didChangeAccessibilityFeatures() in $this'); } return true; }()); @@ -1334,8 +1315,7 @@ abstract class StateX extends State // Record the triggered event assert(() { if (_showWidgetsBinding) { - //ignore: avoid_print - print('============ Event: reassemble() in $this'); + debugPrint('============ Event: reassemble() in $this'); } return true; }()); diff --git a/lib/part05_futurebuilder_state_mixin.dart b/lib/part05_futurebuilder_state_mixin.dart index 8ab9fbd..c219f39 100644 --- a/lib/part05_futurebuilder_state_mixin.dart +++ b/lib/part05_futurebuilder_state_mixin.dart @@ -24,6 +24,16 @@ mixin FutureBuilderStateMixin on State { // Generate the Future evey time or just once if (_runAsync || _future == null) { _future = initAsync(); + _future?.catchError( + (Object e) { + catchAsyncError(e); + // Always false. snapshot.data == false + // snapshot.hasError likely true so ErrorWidget.builder() displayed + return false; + }, + // It's got to be handled, and so it's always true to call catchError() + test: (_) => true, + ); } return FutureBuilder( key: ValueKey(this), @@ -60,6 +70,14 @@ mixin FutureBuilderStateMixin on State { AsyncSnapshot? get snapshot => _snapshot; AsyncSnapshot? _snapshot; + /// initAsync() has failed and a 'error' widget instead will be displayed. + /// This takes in the snapshot.error details. + void onAsyncError(FlutterErrorDetails details) {} + + /// Catch it if the initAsync() throws an error + /// The FutureBuilder will fail, but you can examine the error + void catchAsyncError(Object error) {} + /// Record any splash screen Widget? _splashScreen; @@ -195,10 +213,6 @@ mixin FutureBuilderStateMixin on State { return widget; } - /// Supply an 'error handler' routine if something goes wrong - /// in the corresponding runAsync() or initAsync() routine. - void onAsyncError(FlutterErrorDetails details) {} - /// Is the CupertinoApp being used? bool get usingCupertino => _usingCupertino ??= context.getElementForInheritedWidgetOfExactType< diff --git a/lib/part18_async_ops_mixin.dart b/lib/part18_async_ops_mixin.dart index e349b5f..4a37e41 100644 --- a/lib/part18_async_ops_mixin.dart +++ b/lib/part18_async_ops_mixin.dart @@ -14,8 +14,8 @@ mixin AsyncOps { /// Implement any asynchronous operations needed done at start up. Future initAsync() async => true; - /// Supply an 'error handler' routine if something goes wrong - /// in the corresponding runAsync() routine. + /// initAsync() has failed and a 'error' widget instead will be displayed. + /// This takes in the snapshot.error details. void onAsyncError(FlutterErrorDetails details) {} /// diff --git a/lib/part19_uuid.dart b/lib/part19_uuid.dart index f33b2d2..0dc2cd7 100644 --- a/lib/part19_uuid.dart +++ b/lib/part19_uuid.dart @@ -6,7 +6,6 @@ part of 'state_extended.dart'; -/// A UUID generator, useful for generating unique IDs. /// Shamelessly extracted from the author of Scoped Model plugin, /// Who maybe took from the Flutter source code. I'm not telling! /// diff --git a/pubspec.yaml b/pubspec.yaml index 47b2d07..f810dea 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: state_extended description: This class extends the capabilities of Flutter's State class and includes a controller. -version: 5.0.0+3 +version: 5.1.0 homepage: https://www.andrioussolutions.com repository: https://github.com/AndriousSolutions/state_extended