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

Flutter中使用SharedPreferences保存加载应用配置的最佳实践是什么?

Flutter SharedPreferences 存取应用配置最优实现方案

现有实现存在几个可优化点:

  • 每次存取都调用SharedPreferences.getInstance(),重复产生异步开销,该方法本身是单例,重复调用也会返回同一个实例,但没必要每次都走异步判断
  • 异步加载配置完成后没有调用setState(),会导致界面第一次加载时不会更新最新的存储状态
  • 没有处理存储操作的返回结果,setBool 可能执行失败,直接丢弃返回值会忽略异常场景
  • 存储key硬编码,容易出现拼写错误导致存取不匹配

1. 封装统一的SharedPreferences工具类

缓存全局实例,统一管理配置key,示例代码:

// 全局SP工具类
class SpUtil {
  SpUtil._internal();
  static final SpUtil _instance = SpUtil._internal();
  factory SpUtil() => _instance;

  static late final SharedPreferences _sp;

  // 初始化方法,建议在main函数的runApp之前执行
  static Future<void> init() async {
    _sp = await SharedPreferences.getInstance();
  }

  // 统一管理存储key
  static const String _keyNotificationEnable = 'notificationIsEnabled';

  // 封装存取方法
  bool get notificationEnable => _sp.getBool(_keyNotificationEnable) ?? true;
  Future<bool> setNotificationEnable(bool value) => _sp.setBool(_keyNotificationEnable, value);
}

在main函数里提前初始化,避免页面内的异步等待开销:

void main() async {
  // 确保初始化完成再启动App
  WidgetsFlutterBinding.ensureInitialized();
  await SpUtil.init();
  runApp(const MyApp());
}

2. 优化页面实现

class HomePageState extends State<HomePage> with WidgetsBindingObserver {
  bool notificationIsEnabled = true;
 
  void _loadNotificationState() {
    // 直接同步读取,不需要异步
    setState(() {
      notificationIsEnabled = SpUtil().notificationEnable;
    });
  }

  Future<void> _saveNotificationState(bool value) async {
    bool saveSuccess = await SpUtil().setNotificationEnable(value);
    if (!saveSuccess) {
      // 可选:存储失败时回滚状态,或者给用户提示
      setState(() {
        notificationIsEnabled = !value;
      });
    }
  }

  @override
  void initState() {
    super.initState();
    // 添加生命周期监听
    WidgetsBinding.instance.addObserver(this);
    _loadNotificationState();
  }

  // 监听应用生命周期变化
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    // 对应Android的onPause回调,应用退到后台时触发
    if (state == AppLifecycleState.paused) {
      // 可以在这里执行批量存储操作,适合多配置项的场景,减少IO次数
      _saveNotificationState(notificationIsEnabled);
    }
  }

  @override
  void dispose() {
    // 移除生命周期监听,避免内存泄漏
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Demo App'),
        actions: [
          IconButton(
            onPressed: () async {
              bool newState = !notificationIsEnabled;
              setState(() {
                notificationIsEnabled = newState;
              });
              // 如果是高频修改的配置,可以不用每次点击都存,统一在退后台时存即可
              await _saveNotificationState(newState);
            },
            icon: Icon(notificationIsEnabled
                ? Icons.notifications_on
                : Icons.notifications_off),
          )
        ],
      ),
      body: const SizedBox.expand(),
    );
  }
}
类似Android onPause的生命周期处理说明

Flutter中通过WidgetsBindingObserver监听AppLifecycleState即可实现和Android onPause等效的能力:

  • AppLifecycleState.paused:应用对用户不可见、无法响应用户输入,进入后台状态,完全对应Android Activity的onPause回调
  • 适合批量存储修改后的配置、释放资源等操作,避免频繁的IO操作影响前台性能
  • 注意必须在dispose生命周期移除观察者,否则会产生内存泄漏

内容的提问来源于stack exchange,提问作者AliZ.ece

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 13:06:03