Flutter暗黑模式切换后重启恢复问题求助(Provider+SharedPreferences)
问题分析与解决方案
你的代码核心问题是没有将用户选择的主题模式持久化存储:每次重启App时,ThemeProvider都会重新初始化,themeMode被重置为默认的ThemeMode.dark,导致重启后自动回到暗黑模式。
以下是具体修复步骤:
1. 添加本地存储依赖
在pubspec.yaml中加入shared_preferences(用于本地键值对存储):
dependencies: flutter: sdk: flutter provider: ^6.0.5 shared_preferences: ^2.2.2
执行flutter pub get安装依赖。
2. 修改ThemeProvider,加入持久化逻辑
更新ThemeProvider.dart,在初始化时读取本地存储的主题设置,切换主题时保存设置:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class ThemeProvider extends ChangeNotifier { ThemeMode themeMode = ThemeMode.dark; // 构造函数中加载本地保存的主题 ThemeProvider() { _loadSavedTheme(); } bool get isDarkMode => themeMode == ThemeMode.dark; // 从本地存储读取主题设置 Future<void> _loadSavedTheme() async { final prefs = await SharedPreferences.getInstance(); // 默认值为true(暗黑模式),和初始设置保持一致 final isDark = prefs.getBool('isDarkMode') ?? true; themeMode = isDark ? ThemeMode.dark : ThemeMode.light; notifyListeners(); } // 切换主题并保存到本地 Future<void> toggleTheme(bool isOn) async { themeMode = isOn ? ThemeMode.dark : ThemeMode.light; final prefs = await SharedPreferences.getInstance(); await prefs.setBool('isDarkMode', isOn); notifyListeners(); } }
3. 调整Main.dart,确保异步初始化完成再构建UI
因为读取本地存储是异步操作,需要用FutureBuilder等待初始化完成后再渲染MaterialApp:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() async { // 必须调用此方法,确保在main函数中执行异步操作前绑定Flutter框架 WidgetsFlutterBinding.ensureInitialized(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return FutureBuilder( future: SharedPreferences.getInstance(), builder: (context, snapshot) { // 本地存储未初始化完成时,显示加载过渡界面 if (!snapshot.hasData) { return const MaterialApp( home: Scaffold( body: Center(child: CircularProgressIndicator()), ), ); } return MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => ThemeProvider()), ], child: Builder(builder: (BuildContext context) { final themeProvider = Provider.of<ThemeProvider>(context); return MaterialApp( debugShowCheckedModeBanner: false, title: 'Unit Converter', home: const HomePage(), themeMode: themeProvider.themeMode, theme: MyThemes.lightTheme, darkTheme: MyThemes.darkTheme, ); }), ); }, ); } }
4. Setting_page.dart无需修改
原有的切换逻辑完全正常,toggleTheme变为异步方法不影响SwitchListTile的调用(onChanged不需要等待异步完成,notifyListeners会自动更新UI状态)。
内容的提问来源于stack exchange,提问作者Abu Bakar
相关产品推荐
相关产品推荐

