Skip to content

Commit dcddf2b

Browse files
committed
Reduce boilerplate code in Change Notifier-based hooks
1 parent 319679b commit dcddf2b

11 files changed

+66
-324
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
part of 'hooks.dart';
2+
3+
T _useChangeNotifier<T extends ChangeNotifier>(
4+
ValueGetter<T> builder,
5+
List<Object?>? keys,
6+
) {
7+
return use(_ChangeNotifierHook(builder, keys));
8+
}
9+
10+
class _ChangeNotifierHook<T extends ChangeNotifier> extends Hook<T> {
11+
const _ChangeNotifierHook(
12+
this.builder,
13+
List<Object?>? keys,
14+
) : super(keys: keys);
15+
16+
final ValueGetter<T> builder;
17+
18+
@override
19+
HookState<T, Hook<T>> createState() => _ChangeNotifierHookState<T>(builder);
20+
}
21+
22+
class _ChangeNotifierHookState<T extends ChangeNotifier>
23+
extends HookState<T, _ChangeNotifierHook<T>> {
24+
_ChangeNotifierHookState(ValueGetter<T> builder) : controller = builder();
25+
26+
final T controller;
27+
28+
@override
29+
String get debugLabel => 'use${controller.runtimeType}';
30+
31+
@override
32+
T build(BuildContext context) => controller;
33+
34+
@override
35+
void dispose() => controller.dispose();
36+
}

packages/flutter_hooks/lib/src/draggable_scrollable_controller.dart

+1-24
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,5 @@ part of 'hooks.dart';
77
DraggableScrollableController useDraggableScrollableController({
88
List<Object?>? keys,
99
}) {
10-
return use(_DraggableScrollableControllerHook(keys: keys));
11-
}
12-
13-
class _DraggableScrollableControllerHook
14-
extends Hook<DraggableScrollableController> {
15-
const _DraggableScrollableControllerHook({super.keys});
16-
17-
@override
18-
HookState<DraggableScrollableController, Hook<DraggableScrollableController>>
19-
createState() => _DraggableScrollableControllerHookState();
20-
}
21-
22-
class _DraggableScrollableControllerHookState extends HookState<
23-
DraggableScrollableController, _DraggableScrollableControllerHook> {
24-
final controller = DraggableScrollableController();
25-
26-
@override
27-
String get debugLabel => 'useDraggableScrollableController';
28-
29-
@override
30-
DraggableScrollableController build(BuildContext context) => controller;
31-
32-
@override
33-
void dispose() => controller.dispose();
10+
return _useChangeNotifier(DraggableScrollableController.new, keys);
3411
}

packages/flutter_hooks/lib/src/fixed_extent_scroll_controller.dart

+9-43
Original file line numberDiff line numberDiff line change
@@ -10,48 +10,14 @@ FixedExtentScrollController useFixedExtentScrollController({
1010
ScrollControllerCallback? onDetach,
1111
List<Object?>? keys,
1212
}) {
13-
return use(
14-
_FixedExtentScrollControllerHook(
15-
initialItem: initialItem,
16-
onAttach: onAttach,
17-
onDetach: onDetach,
18-
keys: keys,
19-
),
13+
return _useChangeNotifier(
14+
() {
15+
return FixedExtentScrollController(
16+
initialItem: initialItem,
17+
onAttach: onAttach,
18+
onDetach: onDetach,
19+
);
20+
},
21+
keys,
2022
);
2123
}
22-
23-
class _FixedExtentScrollControllerHook
24-
extends Hook<FixedExtentScrollController> {
25-
const _FixedExtentScrollControllerHook({
26-
required this.initialItem,
27-
this.onAttach,
28-
this.onDetach,
29-
super.keys,
30-
});
31-
32-
final int initialItem;
33-
final ScrollControllerCallback? onAttach;
34-
final ScrollControllerCallback? onDetach;
35-
36-
@override
37-
HookState<FixedExtentScrollController, Hook<FixedExtentScrollController>>
38-
createState() => _FixedExtentScrollControllerHookState();
39-
}
40-
41-
class _FixedExtentScrollControllerHookState extends HookState<
42-
FixedExtentScrollController, _FixedExtentScrollControllerHook> {
43-
late final controller = FixedExtentScrollController(
44-
initialItem: hook.initialItem,
45-
onAttach: hook.onAttach,
46-
onDetach: hook.onDetach,
47-
);
48-
49-
@override
50-
FixedExtentScrollController build(BuildContext context) => controller;
51-
52-
@override
53-
void dispose() => controller.dispose();
54-
55-
@override
56-
String get debugLabel => 'useFixedExtentScrollController';
57-
}

packages/flutter_hooks/lib/src/hooks.dart

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'framework.dart';
1717

1818
part 'animation.dart';
1919
part 'async.dart';
20+
part 'change_notifier.dart';
2021
part 'draggable_scrollable_controller.dart';
2122
part 'expansion_tile_controller.dart';
2223
part 'fixed_extent_scroll_controller.dart';

packages/flutter_hooks/lib/src/page_controller.dart

+3-44
Original file line numberDiff line numberDiff line change
@@ -12,55 +12,14 @@ PageController usePageController({
1212
ScrollControllerCallback? onDetach,
1313
List<Object?>? keys,
1414
}) {
15-
return use(
16-
_PageControllerHook(
15+
return _useChangeNotifier(
16+
() => PageController(
1717
initialPage: initialPage,
1818
keepPage: keepPage,
1919
viewportFraction: viewportFraction,
2020
onAttach: onAttach,
2121
onDetach: onDetach,
22-
keys: keys,
2322
),
23+
keys,
2424
);
2525
}
26-
27-
class _PageControllerHook extends Hook<PageController> {
28-
const _PageControllerHook({
29-
required this.initialPage,
30-
required this.keepPage,
31-
required this.viewportFraction,
32-
this.onAttach,
33-
this.onDetach,
34-
List<Object?>? keys,
35-
}) : super(keys: keys);
36-
37-
final int initialPage;
38-
final bool keepPage;
39-
final double viewportFraction;
40-
final ScrollControllerCallback? onAttach;
41-
final ScrollControllerCallback? onDetach;
42-
43-
@override
44-
HookState<PageController, Hook<PageController>> createState() =>
45-
_PageControllerHookState();
46-
}
47-
48-
class _PageControllerHookState
49-
extends HookState<PageController, _PageControllerHook> {
50-
late final controller = PageController(
51-
initialPage: hook.initialPage,
52-
keepPage: hook.keepPage,
53-
viewportFraction: hook.viewportFraction,
54-
onAttach: hook.onAttach,
55-
onDetach: hook.onDetach,
56-
);
57-
58-
@override
59-
PageController build(BuildContext context) => controller;
60-
61-
@override
62-
void dispose() => controller.dispose();
63-
64-
@override
65-
String get debugLabel => 'usePageController';
66-
}

packages/flutter_hooks/lib/src/scroll_controller.dart

+3-44
Original file line numberDiff line numberDiff line change
@@ -12,55 +12,14 @@ ScrollController useScrollController({
1212
ScrollControllerCallback? onDetach,
1313
List<Object?>? keys,
1414
}) {
15-
return use(
16-
_ScrollControllerHook(
15+
return _useChangeNotifier(
16+
() => ScrollController(
1717
initialScrollOffset: initialScrollOffset,
1818
keepScrollOffset: keepScrollOffset,
1919
debugLabel: debugLabel,
2020
onAttach: onAttach,
2121
onDetach: onDetach,
22-
keys: keys,
2322
),
23+
keys,
2424
);
2525
}
26-
27-
class _ScrollControllerHook extends Hook<ScrollController> {
28-
const _ScrollControllerHook({
29-
required this.initialScrollOffset,
30-
required this.keepScrollOffset,
31-
this.debugLabel,
32-
this.onAttach,
33-
this.onDetach,
34-
List<Object?>? keys,
35-
}) : super(keys: keys);
36-
37-
final double initialScrollOffset;
38-
final bool keepScrollOffset;
39-
final String? debugLabel;
40-
final ScrollControllerCallback? onAttach;
41-
final ScrollControllerCallback? onDetach;
42-
43-
@override
44-
HookState<ScrollController, Hook<ScrollController>> createState() =>
45-
_ScrollControllerHookState();
46-
}
47-
48-
class _ScrollControllerHookState
49-
extends HookState<ScrollController, _ScrollControllerHook> {
50-
late final controller = ScrollController(
51-
initialScrollOffset: hook.initialScrollOffset,
52-
keepScrollOffset: hook.keepScrollOffset,
53-
debugLabel: hook.debugLabel,
54-
onAttach: hook.onAttach,
55-
onDetach: hook.onDetach,
56-
);
57-
58-
@override
59-
ScrollController build(BuildContext context) => controller;
60-
61-
@override
62-
void dispose() => controller.dispose();
63-
64-
@override
65-
String get debugLabel => 'useScrollController';
66-
}

packages/flutter_hooks/lib/src/search_controller.dart

+1-23
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,5 @@ part of 'hooks.dart';
55
/// See also:
66
/// - [SearchController]
77
SearchController useSearchController({List<Object?>? keys}) {
8-
return use(_SearchControllerHook(keys: keys));
9-
}
10-
11-
class _SearchControllerHook extends Hook<SearchController> {
12-
const _SearchControllerHook({List<Object?>? keys}) : super(keys: keys);
13-
14-
@override
15-
HookState<SearchController, Hook<SearchController>> createState() =>
16-
_SearchControllerHookState();
17-
}
18-
19-
class _SearchControllerHookState
20-
extends HookState<SearchController, _SearchControllerHook> {
21-
final controller = SearchController();
22-
23-
@override
24-
String get debugLabel => 'useSearchController';
25-
26-
@override
27-
SearchController build(BuildContext context) => controller;
28-
29-
@override
30-
void dispose() => controller.dispose();
8+
return _useChangeNotifier(SearchController.new, keys);
319
}

packages/flutter_hooks/lib/src/tab_controller.dart

+5-40
Original file line numberDiff line numberDiff line change
@@ -11,48 +11,13 @@ TabController useTabController({
1111
List<Object?>? keys,
1212
}) {
1313
vsync ??= useSingleTickerProvider(keys: keys);
14-
15-
return use(
16-
_TabControllerHook(
17-
vsync: vsync,
14+
final localVsync = vsync;
15+
return _useChangeNotifier(
16+
() => TabController(
17+
vsync: localVsync,
1818
length: initialLength,
1919
initialIndex: initialIndex,
20-
keys: keys,
2120
),
21+
keys,
2222
);
2323
}
24-
25-
class _TabControllerHook extends Hook<TabController> {
26-
const _TabControllerHook({
27-
required this.length,
28-
required this.vsync,
29-
required this.initialIndex,
30-
List<Object?>? keys,
31-
}) : super(keys: keys);
32-
33-
final int length;
34-
final TickerProvider vsync;
35-
final int initialIndex;
36-
37-
@override
38-
HookState<TabController, Hook<TabController>> createState() =>
39-
_TabControllerHookState();
40-
}
41-
42-
class _TabControllerHookState
43-
extends HookState<TabController, _TabControllerHook> {
44-
late final controller = TabController(
45-
length: hook.length,
46-
initialIndex: hook.initialIndex,
47-
vsync: hook.vsync,
48-
);
49-
50-
@override
51-
TabController build(BuildContext context) => controller;
52-
53-
@override
54-
void dispose() => controller.dispose();
55-
56-
@override
57-
String get debugLabel => 'useTabController';
58-
}

packages/flutter_hooks/lib/src/text_controller.dart

+5-40
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class _TextEditingControllerHookCreator {
88
/// The [text] parameter can be used to set the initial value of the
99
/// controller.
1010
TextEditingController call({String? text, List<Object?>? keys}) {
11-
return use(_TextEditingControllerHook(text, keys));
11+
return _useChangeNotifier(() => TextEditingController(text: text), keys);
1212
}
1313

1414
/// Creates a [TextEditingController] from the initial [value] that will
@@ -17,7 +17,10 @@ class _TextEditingControllerHookCreator {
1717
TextEditingValue value, [
1818
List<Object?>? keys,
1919
]) {
20-
return use(_TextEditingControllerHook.fromValue(value, keys));
20+
return _useChangeNotifier(
21+
() => TextEditingController.fromValue(value),
22+
keys,
23+
);
2124
}
2225
}
2326

@@ -54,41 +57,3 @@ class _TextEditingControllerHookCreator {
5457
/// See also:
5558
/// - [TextEditingController], which this hook creates.
5659
const useTextEditingController = _TextEditingControllerHookCreator();
57-
58-
class _TextEditingControllerHook extends Hook<TextEditingController> {
59-
const _TextEditingControllerHook(
60-
this.initialText, [
61-
List<Object?>? keys,
62-
]) : initialValue = null,
63-
super(keys: keys);
64-
65-
const _TextEditingControllerHook.fromValue(
66-
TextEditingValue this.initialValue, [
67-
List<Object?>? keys,
68-
]) : initialText = null,
69-
super(keys: keys);
70-
71-
final String? initialText;
72-
final TextEditingValue? initialValue;
73-
74-
@override
75-
_TextEditingControllerHookState createState() {
76-
return _TextEditingControllerHookState();
77-
}
78-
}
79-
80-
class _TextEditingControllerHookState
81-
extends HookState<TextEditingController, _TextEditingControllerHook> {
82-
late final _controller = hook.initialValue != null
83-
? TextEditingController.fromValue(hook.initialValue)
84-
: TextEditingController(text: hook.initialText);
85-
86-
@override
87-
TextEditingController build(BuildContext context) => _controller;
88-
89-
@override
90-
void dispose() => _controller.dispose();
91-
92-
@override
93-
String get debugLabel => 'useTextEditingController';
94-
}

0 commit comments

Comments
 (0)