Flutter中Switch+SharedPreferences切换主题重启失效问题排查
问题核心
你的问题出在ThemeManager初始化时没有读取SharedPreferences中保存的主题状态,每次重启App它都会默认回到ThemeMode.light,而Switch的状态是从SharedPreferences加载的,所以出现Switch状态保留但主题重置的矛盾。
正确的做法是把SharedPreferences的逻辑整合到ThemeManager中,让主题管理器自身负责状态的持久化与读取,这样UI层只需要和ThemeManager交互即可。
修改方案
1. 重构theme_manager.dart
让ThemeManager完全接管主题的加载、切换与持久化:
import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter/material.dart'; class ThemeManager extends ChangeNotifier { ThemeMode _themeMode = ThemeMode.light; static const String _themeKey = "colorMode"; ThemeMode get themeMode => _themeMode; // 构造时自动加载保存的主题 ThemeManager() { _loadSavedTheme(); } Future<void> _loadSavedTheme() async { final prefs = await SharedPreferences.getInstance(); // 默认值设为false(浅色主题) bool isDark = prefs.getBool(_themeKey) ?? false; _themeMode = isDark ? ThemeMode.dark : ThemeMode.light; notifyListeners(); } Future<void> toggleTheme(bool isDark) async { _themeMode = isDark ? ThemeMode.dark : ThemeMode.light; // 保存状态到SharedPreferences final prefs = await SharedPreferences.getInstance(); await prefs.setBool(_themeKey, isDark); notifyListeners(); } }
2. 简化theme.dart中的代码
移除本地的SharedPreferences相关逻辑,直接通过Provider与ThemeManager交互:
// 不需要再定义本地colorMode变量,直接从ThemeManager获取状态 bool get colorMode => Provider.of<ThemeManager>(context).themeMode == ThemeMode.dark; @override Widget build(BuildContext context) { return Switch( activeColor: Colors.grey, value: colorMode, onChanged: (bool value) { // 调用ThemeManager的切换方法 Provider.of<ThemeManager>(context, listen: false).toggleTheme(value); }, ); } // 移除原来的initState、getSwitchValues、savebool、loadbool方法
3. 调整main.dart的主题引用
确保MaterialApp使用你在theme_constant.dart中定义的自定义主题:
ThemeManager themeManager = ThemeManager(); // ... 其他代码不变 MultiProvider( providers: [ Provider(create: (_) => User), ChangeNotifierProvider(create: (context) => themeManager) ], child: MaterialApp( title: 'My app', themeMode: themeManager.themeMode, theme: lightTheme, // 引用theme_constant中的浅色主题 darkTheme: darkTheme, // 引用theme_constant中的深色主题 home: const LoginScreen(), debugShowCheckedModeBanner: false, ), );
补充说明
theme_constant.dart中的主题定义没有问题,只要在MaterialApp中正确引用即可生效。重构后,ThemeManager完全接管主题状态的管理与持久化,避免了状态分散导致的不同步问题。
内容的提问来源于stack exchange,提问作者It'sPhil
相关产品推荐
相关产品推荐

