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

Flutter中ChangeNotifier子类初始化主题状态失败求助

问题原因及解决方案

你的代码存在两个核心问题,导致主题初始化失效:

1. 异步初始化未触发UI更新

init()方法修改_isDarkMode后,没有调用notifyListeners(),Consumer无法感知状态变化,UI会一直停留在初始的深色模式(默认值_isDarkMode = true)。

2. 异步初始化未等待完成

在ChangeNotifierProvider的create方法中调用prefs.init()时,没有等待异步操作完成就返回了实例。此时UI已经基于初始值渲染,后续初始化完成后也不会触发UI重建。


修复步骤:

第一步:更新PreferencesModel的init方法

添加notifyListeners()通知UI状态变化:

class PreferencesModel extends ChangeNotifier {
  static const _darkModeSetting = "darkmode";

  bool _isDarkMode = true; // default, overridden by init()

  bool get isDarkMode => _isDarkMode;

  ThemeData get appTheme => _isDarkMode ? AppThemes.darkTheme : AppThemes.lightTheme;

  void init() async {
    final prefs = await SharedPreferences.getInstance();
    final bool? dark = prefs.getBool(_darkModeSetting);
    _isDarkMode = dark ?? false;
    await prefs.setBool(_darkModeSetting, _isDarkMode);
    notifyListeners(); // 新增:通知UI更新最新状态
  }

  void setDarkMode(bool isDark) async {
    print("setting preferences dark mode to ${isDark}");
    final prefs = await SharedPreferences.getInstance();
    await prefs.setBool(_darkModeSetting, isDark);
    _isDarkMode = isDark;
    notifyListeners();
  }
}

第二步:确保初始化完成后再启动App

修改main函数,先等待PreferencesModel初始化完成再运行App:

void main() async {
  // 必须调用此方法,才能在main函数中使用异步操作
  WidgetsFlutterBinding.ensureInitialized();
  
  final prefsModel = PreferencesModel();
  await prefsModel.init(); // 等待初始化完成
  
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider.value(value: prefsModel),
      ],
      child: const MyApp(),
    )
  );
}

可选方案:用FutureBuilder处理加载状态

如果不想阻塞App启动,可以在MyApp中用FutureBuilder显示加载界面,等待初始化完成后再渲染主题:

class _MyAppState extends State<MyApp> {
  late Future<void> _initFuture;

  @override
  void initState() {
    super.initState();
    // 获取Provider实例并启动初始化,listen: false避免不必要的重建
    _initFuture = Provider.of<PreferencesModel>(context, listen: false).init();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _initFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return Consumer<PreferencesModel>(
            builder: (context, preferences, child) {
              return MaterialApp(
                title: 'MyApp',
                home: MainPage(title: 'MyApp'),
                theme: AppThemes.lightTheme,
                darkTheme: AppThemes.darkTheme,
                themeMode: preferences.isDarkMode ? ThemeMode.dark : ThemeMode.light,
              );
            }
          );
        } else {
          // 初始化过程中显示加载动画
          return const Center(child: CircularProgressIndicator());
        }
      },
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 14:15:39