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

Flutter使用shared_preferences时不同函数间数据不同步如何解决

根本原因

你遇到的是 android_alarm_manager_plus 最常见的踩坑点:它触发的定时回调运行在独立的Dart Isolate中,和App主业务的Isolate内存完全隔离,不存在任何共享的内存变量。
你在主Isolate中初始化的全局storage.sharedPrefs单例,和Alarm回调Isolate中访问的SharedPreferences是完全独立的两个实例,各自持有内存缓存,默认不会和磁盘自动同步,所以才会出现两边读写不一致的情况。你之前在主Isolate调用reload()对Alarm的Isolate完全无效,反之亦然。

解决方案

按以下步骤修改即可解决同步问题:

  1. Alarm回调内每次读写前强制重载
    在你的schedule()函数最开始,先获取当前Isolate的SharedPreferences实例,强制从磁盘同步最新数据,忽略本地缓存:
Future<void> schedule() async {
  // 独立Isolate内单独获取实例,不要用主Isolate的全局单例
  final prefs = await SharedPreferences.getInstance();
  // 强制从磁盘重载,拉取最新值
  await prefs.reload();

  // 后续所有读写都用这个prefs实例
  final lastSchedulingDate = prefs.getString('dateOfLastScheduling');
  // 你的业务调度逻辑...

  // 所有写入操作必须await,确保刷到磁盘
  await prefs.setString('dateOfLastScheduling', DateTime.now().toIso8601String());
  await prefs.setStringList('scheduledTasks', yourNewTaskList);
}
  1. 主Isolate修改后确保落盘
    主Isolate所有对SharedPreferences的写入操作,必须await对应的set方法返回,不要省略异步等待,避免修改只存在于内存缓存还没刷到磁盘。
  2. 跨Isolate状态更新通知(可选,用于UI即时刷新)
    如果需要主Isolate的UI即时感知到Alarm回调里的修改,可以通过Isolate通信机制实现:
  • 主Isolate提前注册通信端口:
import 'dart:isolate';

// 主Isolate初始化阶段执行
final mainReceivePort = ReceivePort();
IsolateNameServer.registerPortWithName(mainReceivePort.sendPort, 'main_notify_port');

// 监听Alarm回调的更新通知
mainReceivePort.listen((message) {
  if (message == 'sp_updated') {
    // 主Isolate重载SharedPreferences缓存
    await storage.sharedPrefs.reload();
    // 刷新任务列表UI即可
    setState(() {});
  }
});
  • 在schedule()函数写入完成后发送通知:
// schedule()函数写入操作完成后添加
final mainPort = IsolateNameServer.lookupPortByName('main_notify_port');
mainPort?.send('sp_updated');
注意事项

SharedPreferences的内存单例仅在单个Isolate内有效,跨Isolate的状态同步必须依赖磁盘作为中间层,配合强制重载+消息通知实现完全一致的读写效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 07:24:00