Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce boilerplate code in Change Notifier-based hooks #440

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions packages/flutter_hooks/lib/src/change_notifier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
part of 'hooks.dart';

T _useChangeNotifier<T extends ChangeNotifier>(
ValueGetter<T> builder,
List<Object?>? keys,
) {
return use(_ChangeNotifierHook(builder, keys));
}

class _ChangeNotifierHook<T extends ChangeNotifier> extends Hook<T> {
const _ChangeNotifierHook(
this.builder,
List<Object?>? keys,
) : super(keys: keys);

final ValueGetter<T> builder;

@override
HookState<T, Hook<T>> createState() => _ChangeNotifierHookState<T>(builder);
}

class _ChangeNotifierHookState<T extends ChangeNotifier>
extends HookState<T, _ChangeNotifierHook<T>> {
_ChangeNotifierHookState(ValueGetter<T> builder) : controller = builder();

final T controller;

@override
String get debugLabel => 'use${controller.runtimeType}';

@override
T build(BuildContext context) => controller;

@override
void dispose() => controller.dispose();
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,5 @@ part of 'hooks.dart';
DraggableScrollableController useDraggableScrollableController({
List<Object?>? keys,
}) {
return use(_DraggableScrollableControllerHook(keys: keys));
}

class _DraggableScrollableControllerHook
extends Hook<DraggableScrollableController> {
const _DraggableScrollableControllerHook({super.keys});

@override
HookState<DraggableScrollableController, Hook<DraggableScrollableController>>
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);
}
52 changes: 9 additions & 43 deletions packages/flutter_hooks/lib/src/fixed_extent_scroll_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,14 @@ FixedExtentScrollController useFixedExtentScrollController({
ScrollControllerCallback? onDetach,
List<Object?>? 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<FixedExtentScrollController> {
const _FixedExtentScrollControllerHook({
required this.initialItem,
this.onAttach,
this.onDetach,
super.keys,
});

final int initialItem;
final ScrollControllerCallback? onAttach;
final ScrollControllerCallback? onDetach;

@override
HookState<FixedExtentScrollController, Hook<FixedExtentScrollController>>
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';
}
1 change: 1 addition & 0 deletions packages/flutter_hooks/lib/src/hooks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
47 changes: 3 additions & 44 deletions packages/flutter_hooks/lib/src/page_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,55 +12,14 @@ PageController usePageController({
ScrollControllerCallback? onDetach,
List<Object?>? keys,
}) {
return use(
_PageControllerHook(
return _useChangeNotifier(
() => PageController(
initialPage: initialPage,
keepPage: keepPage,
viewportFraction: viewportFraction,
onAttach: onAttach,
onDetach: onDetach,
keys: keys,
),
keys,
);
}

class _PageControllerHook extends Hook<PageController> {
const _PageControllerHook({
required this.initialPage,
required this.keepPage,
required this.viewportFraction,
this.onAttach,
this.onDetach,
List<Object?>? keys,
}) : super(keys: keys);

final int initialPage;
final bool keepPage;
final double viewportFraction;
final ScrollControllerCallback? onAttach;
final ScrollControllerCallback? onDetach;

@override
HookState<PageController, Hook<PageController>> createState() =>
_PageControllerHookState();
}

class _PageControllerHookState
extends HookState<PageController, _PageControllerHook> {
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';
}
47 changes: 3 additions & 44 deletions packages/flutter_hooks/lib/src/scroll_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,55 +12,14 @@ ScrollController useScrollController({
ScrollControllerCallback? onDetach,
List<Object?>? keys,
}) {
return use(
_ScrollControllerHook(
return _useChangeNotifier(
() => ScrollController(
initialScrollOffset: initialScrollOffset,
keepScrollOffset: keepScrollOffset,
debugLabel: debugLabel,
onAttach: onAttach,
onDetach: onDetach,
keys: keys,
),
keys,
);
}

class _ScrollControllerHook extends Hook<ScrollController> {
const _ScrollControllerHook({
required this.initialScrollOffset,
required this.keepScrollOffset,
this.debugLabel,
this.onAttach,
this.onDetach,
List<Object?>? keys,
}) : super(keys: keys);

final double initialScrollOffset;
final bool keepScrollOffset;
final String? debugLabel;
final ScrollControllerCallback? onAttach;
final ScrollControllerCallback? onDetach;

@override
HookState<ScrollController, Hook<ScrollController>> createState() =>
_ScrollControllerHookState();
}

class _ScrollControllerHookState
extends HookState<ScrollController, _ScrollControllerHook> {
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';
}
24 changes: 1 addition & 23 deletions packages/flutter_hooks/lib/src/search_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,5 @@ part of 'hooks.dart';
/// See also:
/// - [SearchController]
SearchController useSearchController({List<Object?>? keys}) {
return use(_SearchControllerHook(keys: keys));
}

class _SearchControllerHook extends Hook<SearchController> {
const _SearchControllerHook({List<Object?>? keys}) : super(keys: keys);

@override
HookState<SearchController, Hook<SearchController>> createState() =>
_SearchControllerHookState();
}

class _SearchControllerHookState
extends HookState<SearchController, _SearchControllerHook> {
final controller = SearchController();

@override
String get debugLabel => 'useSearchController';

@override
SearchController build(BuildContext context) => controller;

@override
void dispose() => controller.dispose();
return _useChangeNotifier(SearchController.new, keys);
}
45 changes: 5 additions & 40 deletions packages/flutter_hooks/lib/src/tab_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,48 +11,13 @@ TabController useTabController({
List<Object?>? 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<TabController> {
const _TabControllerHook({
required this.length,
required this.vsync,
required this.initialIndex,
List<Object?>? keys,
}) : super(keys: keys);

final int length;
final TickerProvider vsync;
final int initialIndex;

@override
HookState<TabController, Hook<TabController>> createState() =>
_TabControllerHookState();
}

class _TabControllerHookState
extends HookState<TabController, _TabControllerHook> {
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';
}
45 changes: 5 additions & 40 deletions packages/flutter_hooks/lib/src/text_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<Object?>? keys}) {
return use(_TextEditingControllerHook(text, keys));
return _useChangeNotifier(() => TextEditingController(text: text), keys);
}

/// Creates a [TextEditingController] from the initial [value] that will
Expand All @@ -17,7 +17,10 @@ class _TextEditingControllerHookCreator {
TextEditingValue value, [
List<Object?>? keys,
]) {
return use(_TextEditingControllerHook.fromValue(value, keys));
return _useChangeNotifier(
() => TextEditingController.fromValue(value),
keys,
);
}
}

Expand Down Expand Up @@ -54,41 +57,3 @@ class _TextEditingControllerHookCreator {
/// See also:
/// - [TextEditingController], which this hook creates.
const useTextEditingController = _TextEditingControllerHookCreator();

class _TextEditingControllerHook extends Hook<TextEditingController> {
const _TextEditingControllerHook(
this.initialText, [
List<Object?>? keys,
]) : initialValue = null,
super(keys: keys);

const _TextEditingControllerHook.fromValue(
TextEditingValue this.initialValue, [
List<Object?>? keys,
]) : initialText = null,
super(keys: keys);

final String? initialText;
final TextEditingValue? initialValue;

@override
_TextEditingControllerHookState createState() {
return _TextEditingControllerHookState();
}
}

class _TextEditingControllerHookState
extends HookState<TextEditingController, _TextEditingControllerHook> {
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';
}
Loading