You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter深色模式切换Switch组件视觉状态不更新问题

问题描述

我基于SharedPreferences和Provider实现了深色/浅色模式切换开关,主题切换功能正常,SharedPreferences也能正确保存布尔值,但存在一个问题:打开侧边菜单切换到深色模式后,退出再打开侧边菜单,Switch组件视觉上仍显示为关闭状态,尽管实际值是正确的。

原因分析

  1. checkTheme方法中更新isDarkMode后未调用setState,UI无法感知状态变化,始终显示初始值
  2. Drawer的initState仅执行一次,后续SharedPreferences值变化时,Drawer状态未同步更新
  3. Provider的ThemeManager未维护深色模式的布尔状态,无法直接从Provider获取当前主题状态

解决方案

1. 修复checkTheme方法,触发UI刷新

在获取SharedPreferences值后,通过setState更新UI:

checkTheme() async {
  SharedPreferences themePref = await SharedPreferences.getInstance();

  setState(() {
    isDarkMode = themePref.containsKey('themeVal') 
        ? themePref.getBool('themeVal')! 
        : false;
  });

  print(isDarkMode);
}

2. 同步Drawer每次打开时的状态

重写didChangeDependencies方法,确保每次打开Drawer都重新获取最新状态:

@override
void didChangeDependencies() {
  checkTheme();
  super.didChangeDependencies();
}

3. 优化Provider的状态管理

修改ThemeManager,添加isDarkMode变量维护当前主题状态:

class ThemeManager extends ChangeNotifier {
  late ThemeData _themeData;
  late bool _isDarkMode;

  ThemeManager(bool isActive) {
    _isDarkMode = isActive ?? false;
    _themeData = _isDarkMode ? midnightDark : morningLight;
  }

  ThemeData get themeData => _themeData;
  bool get isDarkMode => _isDarkMode;

  void setThemeData(ThemeData data, bool isDark) {
    _themeData = data;
    _isDarkMode = isDark;
    notifyListeners();
  }
}

在Drawer中直接从Provider获取状态,无需自行维护:

@override
Widget build(BuildContext context) {
  final themeManager = Provider.of<ThemeManager>(context);
  ThemePreference themePreference = ThemePreference();
  final TextStyle? textTheme = Theme.of(context).textTheme.labelMedium;
  final Color? iconColor = Theme.of(context).iconTheme.color;

  return Column(
    // ... 其他代码
    trailing: Switch(
      value: themeManager.isDarkMode,
      onChanged: (newValue) {
        if (newValue) {
          themeManager.setThemeData(midnightDark, true);
          themePreference.setThemeInfo('themeVal', true);
        } else {
          themeManager.setThemeData(morningLight, false);
          themePreference.setThemeInfo('themeVal', false);
        }
      },
      // ... Switch其他配置
    ),
    // ... 其他代码
  );
}

4. 初始化Provider时传入正确初始值

在App入口先读取SharedPreferences值,再初始化Provider:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  SharedPreferences prefs = await SharedPreferences.getInstance();
  bool isDarkMode = prefs.getBool('themeVal') ?? false;

  runApp(
    ChangeNotifierProvider(
      create: (context) => ThemeManager(isDarkMode),
      child: const MyApp(),
    ),
  );
}

内容的提问来源于stack exchange,提问作者Arun-

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:37:02