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

Flutter技术问询:Shared Preferences启动时值为空如何解决

解决Flutter应用启动时Shared Preferences值为null的问题

兄弟,我太懂这种异步初始化踩坑的感觉了!你遇到的问题本质上是Shared Preferences的初始化是异步操作——应用刚启动时你直接调用prefs.getBool('myBool'),此时Shared Preferences还没完成从本地文件加载数据的过程,自然返回null;而点击按钮时,这个异步操作已经完成了,所以能拿到正确的值。

下面给你几种实用的解决方案,你可以根据自己的应用场景选择:

方案1:在main函数中等待Shared Preferences初始化

这是最直接的方式,确保整个应用在Shared Preferences加载完成后再启动,从根源避免null的问题:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() async {
  // 必须先初始化Flutter绑定,否则异步操作会报错
  WidgetsFlutterBinding.ensureInitialized();
  // 等待Shared Preferences初始化完成
  final prefs = await SharedPreferences.getInstance();
  // 给个默认值兜底,防止首次安装时没有保存过值
  final myBool = prefs.getBool('myBool') ?? false;

  runApp(MyApp(initialMyBool: myBool));
}

class MyApp extends StatelessWidget {
  final bool initialMyBool;

  const MyApp({super.key, required this.initialMyBool});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text('应用启动时的初始值:$initialMyBool'),
        ),
      ),
    );
  }
}

方案2:用FutureBuilder在页面中异步等待加载

如果不想阻塞整个应用启动(比如要先显示启动页),可以在需要用到值的页面用FutureBuilder处理异步状态,给用户展示加载状态:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late Future<bool> _myBoolFuture;

  @override
  void initState() {
    super.initState();
    // 页面初始化时就发起Shared Preferences的获取请求
    _myBoolFuture = _getMyBool();
  }

  Future<bool> _getMyBool() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getBool('myBool') ?? false;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<bool>(
        future: _myBoolFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            // 加载中显示进度条,避免用户看到空白或null
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return const Center(child: Text('加载设置出错啦'));
          } else {
            // 加载完成,展示正确的值
            final myBool = snapshot.data!;
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('当前值:$myBool'),
                  ElevatedButton(
                    onPressed: () async {
                      final prefs = await SharedPreferences.getInstance();
                      await prefs.setBool('myBool', !myBool);
                      // 更新Future,刷新UI展示新值
                      setState(() {
                        _myBoolFuture = _getMyBool();
                      });
                    },
                    child: const Text('切换布尔值'),
                  )
                ],
              ),
            );
          }
        },
      ),
    );
  }
}

方案3:用状态管理工具全局共享(适合复杂应用)

如果你的应用有多个页面需要用到Shared Preferences的值,用状态管理工具(比如Provider)来提前初始化并全局共享是更优雅的选择:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:provider/provider.dart';

class AppSettings extends ChangeNotifier {
  bool _myBool = false;
  late SharedPreferences _prefs;

  bool get myBool => _myBool;

  AppSettings() {
    // 类初始化时自动完成Shared Preferences的加载
    _initSettings();
  }

  Future<void> _initSettings() async {
    _prefs = await SharedPreferences.getInstance();
    _myBool = _prefs.getBool('myBool') ?? false;
    // 通知监听者更新UI
    notifyListeners();
  }

  Future<void> toggleMyBool() async {
    _myBool = !_myBool;
    await _prefs.setBool('myBool', _myBool);
    notifyListeners();
  }
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(
    ChangeNotifierProvider(
      create: (context) => AppSettings(),
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Consumer<AppSettings>(
          builder: (context, settings, child) {
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('全局共享的布尔值:${settings.myBool}'),
                  ElevatedButton(
                    onPressed: () => settings.toggleMyBool(),
                    child: const Text('切换值'),
                  )
                ],
              ),
            );
          },
        ),
      ),
    );
  }
}

核心思路总结

不管用哪种方案,核心都是确保在获取Shared Preferences的值之前,先等待它的初始化异步操作完成。上面三种方案分别对应了:

  • 简单应用的全局阻塞初始化
  • 页面级的异步等待(不阻塞启动)
  • 复杂应用的全局状态管理

你可以根据自己的应用规模和需求来选~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:43:57