From dcddf2bac7d926339763b9e600ae2c44b5963cc3 Mon Sep 17 00:00:00 2001 From: GiAnG Date: Mon, 5 Aug 2024 02:13:14 +0800 Subject: [PATCH] Reduce boilerplate code in `Change Notifier`-based hooks --- .../lib/src/change_notifier.dart | 36 +++++++++++++ .../src/draggable_scrollable_controller.dart | 25 +-------- .../src/fixed_extent_scroll_controller.dart | 52 ++++--------------- packages/flutter_hooks/lib/src/hooks.dart | 1 + .../lib/src/page_controller.dart | 47 ++--------------- .../lib/src/scroll_controller.dart | 47 ++--------------- .../lib/src/search_controller.dart | 24 +-------- .../flutter_hooks/lib/src/tab_controller.dart | 45 ++-------------- .../lib/src/text_controller.dart | 45 ++-------------- .../lib/src/transformation_controller.dart | 34 +----------- .../lib/src/widget_states_controller.dart | 34 +----------- 11 files changed, 66 insertions(+), 324 deletions(-) create mode 100644 packages/flutter_hooks/lib/src/change_notifier.dart diff --git a/packages/flutter_hooks/lib/src/change_notifier.dart b/packages/flutter_hooks/lib/src/change_notifier.dart new file mode 100644 index 00000000..872a80b7 --- /dev/null +++ b/packages/flutter_hooks/lib/src/change_notifier.dart @@ -0,0 +1,36 @@ +part of 'hooks.dart'; + +T _useChangeNotifier( + ValueGetter builder, + List? keys, +) { + return use(_ChangeNotifierHook(builder, keys)); +} + +class _ChangeNotifierHook extends Hook { + const _ChangeNotifierHook( + this.builder, + List? keys, + ) : super(keys: keys); + + final ValueGetter builder; + + @override + HookState> createState() => _ChangeNotifierHookState(builder); +} + +class _ChangeNotifierHookState + extends HookState> { + _ChangeNotifierHookState(ValueGetter builder) : controller = builder(); + + final T controller; + + @override + String get debugLabel => 'use${controller.runtimeType}'; + + @override + T build(BuildContext context) => controller; + + @override + void dispose() => controller.dispose(); +} diff --git a/packages/flutter_hooks/lib/src/draggable_scrollable_controller.dart b/packages/flutter_hooks/lib/src/draggable_scrollable_controller.dart index 621a3392..5e4988c2 100644 --- a/packages/flutter_hooks/lib/src/draggable_scrollable_controller.dart +++ b/packages/flutter_hooks/lib/src/draggable_scrollable_controller.dart @@ -7,28 +7,5 @@ part of 'hooks.dart'; DraggableScrollableController useDraggableScrollableController({ List? keys, }) { - return use(_DraggableScrollableControllerHook(keys: keys)); -} - -class _DraggableScrollableControllerHook - extends Hook { - const _DraggableScrollableControllerHook({super.keys}); - - @override - HookState> - createState() => _DraggableScrollableControllerHookState(); -} - -class _DraggableScrollableControllerHookState extends HookState< - DraggableScrollableController, _DraggableScrollableControllerHook> { - final controller = DraggableScrollableController(); - - @override - String get debugLabel => 'useDraggableScrollableController'; - - @override - DraggableScrollableController build(BuildContext context) => controller; - - @override - void dispose() => controller.dispose(); + return _useChangeNotifier(DraggableScrollableController.new, keys); } diff --git a/packages/flutter_hooks/lib/src/fixed_extent_scroll_controller.dart b/packages/flutter_hooks/lib/src/fixed_extent_scroll_controller.dart index a70a1619..e51de208 100644 --- a/packages/flutter_hooks/lib/src/fixed_extent_scroll_controller.dart +++ b/packages/flutter_hooks/lib/src/fixed_extent_scroll_controller.dart @@ -10,48 +10,14 @@ FixedExtentScrollController useFixedExtentScrollController({ ScrollControllerCallback? onDetach, List? keys, }) { - return use( - _FixedExtentScrollControllerHook( - initialItem: initialItem, - onAttach: onAttach, - onDetach: onDetach, - keys: keys, - ), + return _useChangeNotifier( + () { + return FixedExtentScrollController( + initialItem: initialItem, + onAttach: onAttach, + onDetach: onDetach, + ); + }, + keys, ); } - -class _FixedExtentScrollControllerHook - extends Hook { - const _FixedExtentScrollControllerHook({ - required this.initialItem, - this.onAttach, - this.onDetach, - super.keys, - }); - - final int initialItem; - final ScrollControllerCallback? onAttach; - final ScrollControllerCallback? onDetach; - - @override - HookState> - createState() => _FixedExtentScrollControllerHookState(); -} - -class _FixedExtentScrollControllerHookState extends HookState< - FixedExtentScrollController, _FixedExtentScrollControllerHook> { - late final controller = FixedExtentScrollController( - initialItem: hook.initialItem, - onAttach: hook.onAttach, - onDetach: hook.onDetach, - ); - - @override - FixedExtentScrollController build(BuildContext context) => controller; - - @override - void dispose() => controller.dispose(); - - @override - String get debugLabel => 'useFixedExtentScrollController'; -} diff --git a/packages/flutter_hooks/lib/src/hooks.dart b/packages/flutter_hooks/lib/src/hooks.dart index 023868de..cb63ae1a 100644 --- a/packages/flutter_hooks/lib/src/hooks.dart +++ b/packages/flutter_hooks/lib/src/hooks.dart @@ -17,6 +17,7 @@ import 'framework.dart'; part 'animation.dart'; part 'async.dart'; +part 'change_notifier.dart'; part 'draggable_scrollable_controller.dart'; part 'expansion_tile_controller.dart'; part 'fixed_extent_scroll_controller.dart'; diff --git a/packages/flutter_hooks/lib/src/page_controller.dart b/packages/flutter_hooks/lib/src/page_controller.dart index bbe16734..e3235c95 100644 --- a/packages/flutter_hooks/lib/src/page_controller.dart +++ b/packages/flutter_hooks/lib/src/page_controller.dart @@ -12,55 +12,14 @@ PageController usePageController({ ScrollControllerCallback? onDetach, List? keys, }) { - return use( - _PageControllerHook( + return _useChangeNotifier( + () => PageController( initialPage: initialPage, keepPage: keepPage, viewportFraction: viewportFraction, onAttach: onAttach, onDetach: onDetach, - keys: keys, ), + keys, ); } - -class _PageControllerHook extends Hook { - const _PageControllerHook({ - required this.initialPage, - required this.keepPage, - required this.viewportFraction, - this.onAttach, - this.onDetach, - List? keys, - }) : super(keys: keys); - - final int initialPage; - final bool keepPage; - final double viewportFraction; - final ScrollControllerCallback? onAttach; - final ScrollControllerCallback? onDetach; - - @override - HookState> createState() => - _PageControllerHookState(); -} - -class _PageControllerHookState - extends HookState { - late final controller = PageController( - initialPage: hook.initialPage, - keepPage: hook.keepPage, - viewportFraction: hook.viewportFraction, - onAttach: hook.onAttach, - onDetach: hook.onDetach, - ); - - @override - PageController build(BuildContext context) => controller; - - @override - void dispose() => controller.dispose(); - - @override - String get debugLabel => 'usePageController'; -} diff --git a/packages/flutter_hooks/lib/src/scroll_controller.dart b/packages/flutter_hooks/lib/src/scroll_controller.dart index 1d182cf6..3b0b0c91 100644 --- a/packages/flutter_hooks/lib/src/scroll_controller.dart +++ b/packages/flutter_hooks/lib/src/scroll_controller.dart @@ -12,55 +12,14 @@ ScrollController useScrollController({ ScrollControllerCallback? onDetach, List? keys, }) { - return use( - _ScrollControllerHook( + return _useChangeNotifier( + () => ScrollController( initialScrollOffset: initialScrollOffset, keepScrollOffset: keepScrollOffset, debugLabel: debugLabel, onAttach: onAttach, onDetach: onDetach, - keys: keys, ), + keys, ); } - -class _ScrollControllerHook extends Hook { - const _ScrollControllerHook({ - required this.initialScrollOffset, - required this.keepScrollOffset, - this.debugLabel, - this.onAttach, - this.onDetach, - List? keys, - }) : super(keys: keys); - - final double initialScrollOffset; - final bool keepScrollOffset; - final String? debugLabel; - final ScrollControllerCallback? onAttach; - final ScrollControllerCallback? onDetach; - - @override - HookState> createState() => - _ScrollControllerHookState(); -} - -class _ScrollControllerHookState - extends HookState { - late final controller = ScrollController( - initialScrollOffset: hook.initialScrollOffset, - keepScrollOffset: hook.keepScrollOffset, - debugLabel: hook.debugLabel, - onAttach: hook.onAttach, - onDetach: hook.onDetach, - ); - - @override - ScrollController build(BuildContext context) => controller; - - @override - void dispose() => controller.dispose(); - - @override - String get debugLabel => 'useScrollController'; -} diff --git a/packages/flutter_hooks/lib/src/search_controller.dart b/packages/flutter_hooks/lib/src/search_controller.dart index 454ea6b0..bd843d1a 100644 --- a/packages/flutter_hooks/lib/src/search_controller.dart +++ b/packages/flutter_hooks/lib/src/search_controller.dart @@ -5,27 +5,5 @@ part of 'hooks.dart'; /// See also: /// - [SearchController] SearchController useSearchController({List? keys}) { - return use(_SearchControllerHook(keys: keys)); -} - -class _SearchControllerHook extends Hook { - const _SearchControllerHook({List? keys}) : super(keys: keys); - - @override - HookState> createState() => - _SearchControllerHookState(); -} - -class _SearchControllerHookState - extends HookState { - final controller = SearchController(); - - @override - String get debugLabel => 'useSearchController'; - - @override - SearchController build(BuildContext context) => controller; - - @override - void dispose() => controller.dispose(); + return _useChangeNotifier(SearchController.new, keys); } diff --git a/packages/flutter_hooks/lib/src/tab_controller.dart b/packages/flutter_hooks/lib/src/tab_controller.dart index 5aba96c3..ca07b0ea 100644 --- a/packages/flutter_hooks/lib/src/tab_controller.dart +++ b/packages/flutter_hooks/lib/src/tab_controller.dart @@ -11,48 +11,13 @@ TabController useTabController({ List? keys, }) { vsync ??= useSingleTickerProvider(keys: keys); - - return use( - _TabControllerHook( - vsync: vsync, + final localVsync = vsync; + return _useChangeNotifier( + () => TabController( + vsync: localVsync, length: initialLength, initialIndex: initialIndex, - keys: keys, ), + keys, ); } - -class _TabControllerHook extends Hook { - const _TabControllerHook({ - required this.length, - required this.vsync, - required this.initialIndex, - List? keys, - }) : super(keys: keys); - - final int length; - final TickerProvider vsync; - final int initialIndex; - - @override - HookState> createState() => - _TabControllerHookState(); -} - -class _TabControllerHookState - extends HookState { - late final controller = TabController( - length: hook.length, - initialIndex: hook.initialIndex, - vsync: hook.vsync, - ); - - @override - TabController build(BuildContext context) => controller; - - @override - void dispose() => controller.dispose(); - - @override - String get debugLabel => 'useTabController'; -} diff --git a/packages/flutter_hooks/lib/src/text_controller.dart b/packages/flutter_hooks/lib/src/text_controller.dart index e8f8310d..89febf13 100644 --- a/packages/flutter_hooks/lib/src/text_controller.dart +++ b/packages/flutter_hooks/lib/src/text_controller.dart @@ -8,7 +8,7 @@ class _TextEditingControllerHookCreator { /// The [text] parameter can be used to set the initial value of the /// controller. TextEditingController call({String? text, List? keys}) { - return use(_TextEditingControllerHook(text, keys)); + return _useChangeNotifier(() => TextEditingController(text: text), keys); } /// Creates a [TextEditingController] from the initial [value] that will @@ -17,7 +17,10 @@ class _TextEditingControllerHookCreator { TextEditingValue value, [ List? keys, ]) { - return use(_TextEditingControllerHook.fromValue(value, keys)); + return _useChangeNotifier( + () => TextEditingController.fromValue(value), + keys, + ); } } @@ -54,41 +57,3 @@ class _TextEditingControllerHookCreator { /// See also: /// - [TextEditingController], which this hook creates. const useTextEditingController = _TextEditingControllerHookCreator(); - -class _TextEditingControllerHook extends Hook { - const _TextEditingControllerHook( - this.initialText, [ - List? keys, - ]) : initialValue = null, - super(keys: keys); - - const _TextEditingControllerHook.fromValue( - TextEditingValue this.initialValue, [ - List? keys, - ]) : initialText = null, - super(keys: keys); - - final String? initialText; - final TextEditingValue? initialValue; - - @override - _TextEditingControllerHookState createState() { - return _TextEditingControllerHookState(); - } -} - -class _TextEditingControllerHookState - extends HookState { - late final _controller = hook.initialValue != null - ? TextEditingController.fromValue(hook.initialValue) - : TextEditingController(text: hook.initialText); - - @override - TextEditingController build(BuildContext context) => _controller; - - @override - void dispose() => _controller.dispose(); - - @override - String get debugLabel => 'useTextEditingController'; -} diff --git a/packages/flutter_hooks/lib/src/transformation_controller.dart b/packages/flutter_hooks/lib/src/transformation_controller.dart index d563d17d..cf65e369 100644 --- a/packages/flutter_hooks/lib/src/transformation_controller.dart +++ b/packages/flutter_hooks/lib/src/transformation_controller.dart @@ -8,37 +8,5 @@ TransformationController useTransformationController({ Matrix4? initialValue, List? keys, }) { - return use( - _TransformationControllerHook( - initialValue: initialValue, - keys: keys, - ), - ); -} - -class _TransformationControllerHook extends Hook { - const _TransformationControllerHook({ - required this.initialValue, - List? keys, - }) : super(keys: keys); - - final Matrix4? initialValue; - - @override - HookState> - createState() => _TransformationControllerHookState(); -} - -class _TransformationControllerHookState - extends HookState { - late final controller = TransformationController(hook.initialValue); - - @override - TransformationController build(BuildContext context) => controller; - - @override - void dispose() => controller.dispose(); - - @override - String get debugLabel => 'useTransformationController'; + return _useChangeNotifier(() => TransformationController(initialValue), keys); } diff --git a/packages/flutter_hooks/lib/src/widget_states_controller.dart b/packages/flutter_hooks/lib/src/widget_states_controller.dart index eab0ea2b..b6e8f0eb 100644 --- a/packages/flutter_hooks/lib/src/widget_states_controller.dart +++ b/packages/flutter_hooks/lib/src/widget_states_controller.dart @@ -8,37 +8,5 @@ WidgetStatesController useWidgetStatesController({ Set? values, List? keys, }) { - return use( - _WidgetStatesControllerHook( - values: values, - keys: keys, - ), - ); -} - -class _WidgetStatesControllerHook extends Hook { - const _WidgetStatesControllerHook({ - required this.values, - super.keys, - }); - - final Set? values; - - @override - HookState> - createState() => _WidgetStateControllerHookState(); -} - -class _WidgetStateControllerHookState - extends HookState { - late final controller = WidgetStatesController(hook.values); - - @override - WidgetStatesController build(BuildContext context) => controller; - - @override - void dispose() => controller.dispose(); - - @override - String get debugLabel => 'useWidgetStatesController'; + return _useChangeNotifier(() => WidgetStatesController(values), keys); }