我正在使用Riverpod状态提供程序管理我的Ffltter应用程序的ThemeMode,该模式一直按预期工作,直到我try 读取Theme.of(context)
以获取ThemeData的当前值,这会导致超出(连续13~14次)的小部件重建.所以我决定在Riverpod的repository example之后为ThemeData创建一个提供者,但我仍然会得到这些不必要的重建.我如何防止这些不必要的Riverpod重建以获取ThemeData?为什么会发生这种情况呢?
此代码在github上可用.
主打APP:
final themeProvider = Provider<ThemeData>(
(ref) => throw UnimplementedError(),
dependencies: const [],
);
void main() {
runApp(const ProviderScope(child: MainApp()));
}
class MainApp extends ConsumerWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final ThemeMode themeMode = ref.watch(themeModeStateProvider);
if (kDebugMode) {
print("building app");
}
return MaterialApp(
theme: FlexThemeData.light(scheme: FlexScheme.mandyRed),
darkTheme: FlexThemeData.dark(scheme: FlexScheme.mandyRed),
themeMode: themeMode,
builder: (context, child) {
final theme = Theme.of(context);
return ProviderScope(
overrides: [
themeProvider.overrideWithValue(theme),
],
child: child!,
);
},
home: const HomeScreen(),
);
}
}
主题模式提供程序:
@riverpod
class ThemeModeState extends _$ThemeModeState {
@override
ThemeMode build() {
return ThemeMode.dark;
}
static ThemeMode getSystemTheme(BuildContext context) {
ThemeMode mode = ThemeMode.system;
if (mode == ThemeMode.system) {
if (MediaQuery.of(context).platformBrightness == Brightness.light) {
mode = ThemeMode.light;
} else {
mode = ThemeMode.dark;
}
}
return mode;
}
void toggleThemeMode() {
if (state == ThemeMode.dark) {
state = ThemeMode.light;
} else {
state = ThemeMode.dark;
}
}
}
主屏幕:
class HomeScreen extends ConsumerWidget {
static String routeName = "home";
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final ThemeData themeData = ref.watch(themeProvider);
final TextStyle headlineMedium = themeData.textTheme.headlineLarge!;
if (kDebugMode) {
print("building home");
}
return Scaffold(
body: Center(
child: Column(
children: [
Text(
"Hello World",
style: headlineMedium,
),
SwitchListTile(
contentPadding: EdgeInsets.zero,
title: const Text('Theme mode'),
value: ref.watch(themeModeStateProvider) == ThemeMode.light,
onChanged: (value) {
ref.watch(themeModeStateProvider.notifier).toggleThemeMode();
},
),
],
),
),
);
}
}