Skip to content
This repository was archived by the owner on Apr 3, 2023. It is now read-only.

Commit 6042664

Browse files
committed
Use HookWidget to handle controllers like tab controller and scroll controller (They need to be disposed and have their lifecycle)
1 parent 2aad590 commit 6042664

File tree

6 files changed

+149
-128
lines changed

6 files changed

+149
-128
lines changed

lib/home/home_page.dart

+79-81
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
3+
import 'package:flutter_hooks/flutter_hooks.dart';
34
import 'package:flutter_riverpod/flutter_riverpod.dart';
45

56
import '../midi/midi_model.dart';
@@ -9,91 +10,88 @@ import '../songs/songs_model.dart';
910
import '../songs/songs_widget.dart';
1011
import '../user/user_model.dart';
1112

12-
class HomePage extends StatelessWidget {
13+
class HomePage extends HookWidget {
1314
@override
1415
Widget build(BuildContext context) {
15-
return Scaffold(
16-
body: DefaultTabController(
17-
length: songTags.length,
18-
child: NestedScrollView(
19-
headerSliverBuilder: (context, innerBoxIsScrolled) {
20-
return <Widget>[
21-
SliverAppBar(
22-
title: Text(AppLocalizations.of(context)!.txt_all_songs,
23-
style:
24-
Theme.of(context).appBarTheme.textTheme!.headline5),
25-
elevation: 2,
26-
floating: true,
27-
pinned: true,
28-
snap: true,
29-
forceElevated: true,
30-
actions: [
31-
IconButton(
32-
icon: const Icon(Icons.search_rounded),
33-
onPressed: () {
34-
showSearch<void>(
35-
context: context, delegate: SearchWidget());
36-
},
37-
),
38-
IconButton(
39-
icon: Image(
40-
image:
41-
const AssetImage('assets/images/img_guitar.png'),
42-
color: Theme.of(context).appBarTheme.iconTheme!.color,
43-
),
44-
onPressed: () async {
45-
await Navigator.pushNamed(context, Routes.instrument);
46-
}),
47-
IconButton(icon: ClipOval(child: Consumer(
48-
builder: (context, watch, child) {
49-
// FIXME To load midi
50-
watch(midiProvider);
51-
final user = watch(userProvider);
52-
return user.when(
53-
data: (user) => Image.network(
54-
user.photoUrl,
55-
errorBuilder:
56-
(context, exception, stackTrace) {
57-
return const Icon(
58-
Icons.account_circle_rounded);
59-
},
60-
),
61-
loading: () =>
62-
const Icon(Icons.account_circle_rounded),
63-
error: (_, __) =>
64-
const Icon(Icons.account_circle_rounded));
65-
},
66-
)), onPressed: () async {
67-
await Navigator.pushNamed(context, Routes.account);
68-
}),
69-
IconButton(
70-
icon: const Icon(Icons.settings),
16+
return Scaffold(body: HookBuilder(builder: (context) {
17+
final tabController = useTabController(initialLength: songTags.length);
18+
return NestedScrollView(
19+
headerSliverBuilder: (context, innerBoxIsScrolled) {
20+
return <Widget>[
21+
SliverAppBar(
22+
title: Text(AppLocalizations.of(context)!.txt_all_songs,
23+
style: Theme.of(context).appBarTheme.textTheme!.headline5),
24+
elevation: 2,
25+
floating: true,
26+
pinned: true,
27+
snap: true,
28+
forceElevated: true,
29+
actions: [
30+
IconButton(
31+
icon: const Icon(Icons.search_rounded),
32+
onPressed: () {
33+
showSearch<void>(
34+
context: context, delegate: SearchWidget());
35+
},
36+
),
37+
IconButton(
38+
icon: Image(
39+
image: const AssetImage('assets/images/img_guitar.png'),
40+
color: Theme.of(context).appBarTheme.iconTheme!.color,
41+
),
7142
onPressed: () async {
72-
await Navigator.pushNamed(context, Routes.setting);
73-
},
74-
),
75-
],
76-
bottom: TabBar(
77-
isScrollable: true,
78-
tabs: songTags
79-
.map((tabName) => Tab(
80-
text: getSongTagName(context, tabName),
81-
))
82-
.toList(),
83-
)),
84-
];
85-
},
86-
body: TabBarView(
87-
children: songTags
88-
.asMap()
89-
.map((index, tabName) =>
90-
MapEntry(index, SongsWidget(tag: tabName)))
91-
.values
92-
.toList(),
93-
),
43+
await Navigator.pushNamed(context, Routes.instrument);
44+
}),
45+
IconButton(icon: ClipOval(child: Consumer(
46+
builder: (context, watch, child) {
47+
// FIXME To load midi
48+
watch(midiProvider);
49+
final user = watch(userProvider);
50+
return user.when(
51+
data: (user) => Image.network(
52+
user.photoUrl,
53+
errorBuilder: (context, exception, stackTrace) {
54+
return const Icon(
55+
Icons.account_circle_rounded);
56+
},
57+
),
58+
loading: () =>
59+
const Icon(Icons.account_circle_rounded),
60+
error: (_, __) =>
61+
const Icon(Icons.account_circle_rounded));
62+
},
63+
)), onPressed: () async {
64+
await Navigator.pushNamed(context, Routes.account);
65+
}),
66+
IconButton(
67+
icon: const Icon(Icons.settings),
68+
onPressed: () async {
69+
await Navigator.pushNamed(context, Routes.setting);
70+
},
71+
),
72+
],
73+
bottom: TabBar(
74+
isScrollable: true,
75+
controller: tabController,
76+
tabs: songTags
77+
.map((tabName) => Tab(
78+
text: getSongTagName(context, tabName),
79+
))
80+
.toList(),
81+
)),
82+
];
83+
},
84+
body: TabBarView(
85+
controller: tabController,
86+
children: songTags
87+
.asMap()
88+
.map((index, tabName) =>
89+
MapEntry(index, SongsWidget(tag: tabName)))
90+
.values
91+
.toList(),
9492
),
95-
),
96-
);
93+
);
94+
}));
9795
}
9896
}
9997

lib/locale/locale_page.dart

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
3+
import 'package:flutter_hooks/flutter_hooks.dart';
34
import 'package:flutter_riverpod/flutter_riverpod.dart';
45

56
import 'locale_model.dart';
@@ -11,10 +12,10 @@ const localeStrings = {
1112
'zh': '汉语'
1213
};
1314

14-
class LocalePage extends StatelessWidget {
15+
class LocalePage extends HookWidget {
1516
@override
1617
Widget build(BuildContext context) {
17-
final scrollController = ScrollController();
18+
final scrollController = useScrollController();
1819
return Scaffold(
1920
appBar: AppBar(
2021
title: Text(AppLocalizations.of(context)!.txt_language,

lib/theme/theme_page.dart

+28-24
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,43 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
3+
import 'package:flutter_hooks/flutter_hooks.dart';
34
import 'package:flutter_riverpod/flutter_riverpod.dart';
5+
import 'package:hooks_riverpod/hooks_riverpod.dart';
46

57
import 'theme_model.dart';
68

7-
class ThemePage extends ConsumerWidget {
9+
class ThemePage extends HookWidget {
810
@override
9-
Widget build(BuildContext context, ScopedReader watch) {
10-
final themeMode = watch(themeModeProvider);
11-
final scrollController = ScrollController();
11+
Widget build(BuildContext context) {
1212
return Scaffold(
1313
appBar: AppBar(
1414
title: Text(AppLocalizations.of(context)!.txt_theme,
1515
style: Theme.of(context).appBarTheme.textTheme!.headline5)),
16-
body: Scrollbar(
17-
isAlwaysShown: true,
18-
controller: scrollController,
19-
child: ListView.builder(
16+
body: HookBuilder(builder: (context) {
17+
final scrollController = useScrollController();
18+
final themeMode = useProvider(themeModeProvider);
19+
return Scrollbar(
20+
isAlwaysShown: true,
2021
controller: scrollController,
21-
itemCount: ThemeMode.values.length,
22-
itemBuilder: (context, index) {
23-
return RadioListTile<ThemeMode>(
24-
title: Text(getThemeName(context, ThemeMode.values[index]),
25-
style: Theme.of(context).textTheme.headline6),
26-
value: ThemeMode.values[index],
27-
groupValue: themeMode,
28-
onChanged: (value) {
29-
context
30-
.read(themeModeProvider.notifier)
31-
.setThemeMode(context, value!);
32-
},
33-
);
34-
},
35-
),
36-
));
22+
child: ListView.builder(
23+
controller: scrollController,
24+
itemCount: ThemeMode.values.length,
25+
itemBuilder: (context, index) {
26+
return RadioListTile<ThemeMode>(
27+
title: Text(getThemeName(context, ThemeMode.values[index]),
28+
style: Theme.of(context).textTheme.headline6),
29+
value: ThemeMode.values[index],
30+
groupValue: themeMode,
31+
onChanged: (value) {
32+
context
33+
.read(themeModeProvider.notifier)
34+
.setThemeMode(context, value!);
35+
},
36+
);
37+
},
38+
),
39+
);
40+
}));
3741
}
3842
}
3943

lib/user/user_page.dart

+22-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
3-
import 'package:flutter_riverpod/flutter_riverpod.dart';
3+
import 'package:flutter_hooks/flutter_hooks.dart';
4+
import 'package:hooks_riverpod/hooks_riverpod.dart';
45
import 'package:intl/intl.dart';
56
import 'package:sprintf/sprintf.dart';
67

@@ -10,29 +11,31 @@ import '../loading_widget.dart';
1011
import 'user.dart';
1112
import 'user_model.dart';
1213

13-
class UserPage extends ConsumerWidget {
14+
class UserPage extends HookWidget {
1415
@override
15-
Widget build(BuildContext context, ScopedReader watch) {
16-
final user = watch(userProvider);
16+
Widget build(BuildContext context) {
1717
return Scaffold(
1818
appBar: AppBar(
1919
title: Text(AppLocalizations.of(context)!.txt_page_title_account,
2020
style: Theme.of(context).appBarTheme.textTheme!.headline5)),
21-
body: user.when(
22-
data: (user) {
23-
final scrollController = ScrollController();
24-
return Padding(
25-
padding: const EdgeInsets.all(8),
26-
child: Scrollbar(
27-
isAlwaysShown: true,
28-
controller: scrollController,
29-
child: ListView(
30-
shrinkWrap: true,
31-
controller: scrollController,
32-
children: <Widget>[_buildUI(user, context)])));
33-
},
34-
loading: () => LoadingWidget(),
35-
error: (_, __) => LoadingWidget()));
21+
body: HookBuilder(builder: (context) {
22+
final user = useProvider(userProvider);
23+
return user.when(
24+
data: (user) {
25+
final scrollController = useScrollController();
26+
return Padding(
27+
padding: const EdgeInsets.all(8),
28+
child: Scrollbar(
29+
isAlwaysShown: true,
30+
controller: scrollController,
31+
child: ListView(
32+
shrinkWrap: true,
33+
controller: scrollController,
34+
children: <Widget>[_buildUI(user, context)])));
35+
},
36+
loading: () => LoadingWidget(),
37+
error: (_, __) => LoadingWidget());
38+
}));
3639
}
3740

3841
Widget _buildUI(User user, BuildContext context) {

pubspec.lock

+15-1
Original file line numberDiff line numberDiff line change
@@ -358,13 +358,20 @@ packages:
358358
url: "https://pub.dartlang.org"
359359
source: hosted
360360
version: "2.4.2"
361+
flutter_hooks:
362+
dependency: "direct main"
363+
description:
364+
name: flutter_hooks
365+
url: "https://pub.dartlang.org"
366+
source: hosted
367+
version: "0.17.0"
361368
flutter_localizations:
362369
dependency: "direct main"
363370
description: flutter
364371
source: sdk
365372
version: "0.0.0"
366373
flutter_riverpod:
367-
dependency: "direct main"
374+
dependency: transitive
368375
description:
369376
name: flutter_riverpod
370377
url: "https://pub.dartlang.org"
@@ -431,6 +438,13 @@ packages:
431438
url: "https://pub.dartlang.org"
432439
source: hosted
433440
version: "2.0.0"
441+
hooks_riverpod:
442+
dependency: "direct main"
443+
description:
444+
name: hooks_riverpod
445+
url: "https://pub.dartlang.org"
446+
source: hosted
447+
version: "0.14.0+4"
434448
http:
435449
dependency: transitive
436450
description:

pubspec.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ dependencies:
2121
flutter_cache_manager:
2222
flutter_email_sender:
2323
flutter_facebook_auth:
24-
flutter_riverpod:
24+
flutter_hooks:
2525
freezed_annotation:
2626
google_sign_in:
27+
hooks_riverpod:
2728
in_app_review:
2829
intl:
2930
package_info:

0 commit comments

Comments
 (0)