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

如何更新Flutter后台服务以获取最新SharedPreferences数据?

问题分析与解决方案

1. 优先修正SharedPreferences数据读取的类型错误

你的代码中存在类型获取逻辑错误,这是导致数据显示异常的核心原因:在后台服务的定时任务里,itemName是存入SharedPreferences的字符串类型,你误用了getDouble方法;amount是浮点类型,却用了getString方法,最终只能拿到默认值,看起来像是没获取到最新数据。

修正后的读取代码:

for (int i = 1; i <= totalCount; i++) {
  String key = 'TCID$i';
  // 修正:itemName为String类型,使用getString
  String nme = prefs.getString('$key-itemName') ?? '';
  // 修正:amount为Double类型,使用getDouble
  double amt = prefs.getDouble('$key-amount') ?? 0.0;

  print('TCID $i:');
  print('  - Current Radius: $nme');
  print('  - Destination Title: $amt');
}

2. 优化后台服务的启动与数据同步逻辑

控制台提示Service already running, using existing service说明服务已在运行,重复启动不会重新初始化服务,此时需要通过消息通知服务读取最新数据,而非重复启动。

步骤一:确保服务初始化仅执行一次

将initializeService()放在main函数中执行,避免在页面中重复调用:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await initializeService();
  runApp(const MyApp());
}

步骤二:修改saveDetails的服务调用逻辑

在保存数据后,判断服务状态:已运行则发送刷新消息,未运行则启动服务,同时添加最多3条数据的限制:

Future<void> saveDetails() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  int totalCount = prefs.getInt('idCount') ?? 0;
  
  // 限制最多3条数据
  if (totalCount >= 3) {
    print("最多只能添加3条详情数据");
    return;
  }

  int currentCount = totalCount + 1;
  await prefs.setInt('idCount', currentCount);
  String key = 'TCID$currentCount';
  await prefs.setString('$key-itemName', widget.name);
  await prefs.setDouble('$key-amount', widget.amount);

  final service = FlutterBackgroundService();
  bool isRunning = await service.isRunning();
  if (isRunning) {
    // 发送消息通知服务立即刷新数据
    await service.sendData({'action': 'refresh_data'});
  } else {
    await service.startService();
  }
}

步骤三:在服务中监听刷新消息

修改onStart函数,添加消息监听,收到刷新指令时立即读取最新数据,同时保留定时任务:

@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
  WidgetsFlutterBinding.ensureInitialized();
  if (service is AndroidServiceInstance) {
    service.on('setAsForeground').listen((event) {
      service.setAsForegroundService();
    });
    service.on('setAsBackground').listen((event) {
      service.setAsBackgroundService();
    });
    service.on('stopService').listen((event) {
      service.stopSelf();
    });
    // 监听数据刷新指令
    service.on('refresh_data').listen((event) {
      _fetchAndPrintLatestData();
    });
  }

  // 保留定时任务,周期性执行数据读取
  Timer.periodic(const Duration(seconds: 5), (timer) async {
    if (service is AndroidServiceInstance) {
      if (await service.isForegroundService()) {
        service.setForegroundNotificationInfo(
          title: "My App Service",
          content: "Updated at ${DateTime.now()}",
        );
      }
    }
    await _fetchAndPrintLatestData();
  });
}

// 提取数据读取逻辑为独立函数,便于复用
Future<void> _fetchAndPrintLatestData() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  int totalCount = prefs.getInt('idCount') ?? 0;
  print("---------------------Total idCount stored: $totalCount");
  
  for (int i = 1; i <= totalCount; i++) {
    String key = 'TCID$i';
    String nme = prefs.getString('$key-itemName') ?? '';
    double amt = prefs.getDouble('$key-amount') ?? 0.0;

    print('TCID $i:');
    print('  - Current Radius: $nme');
    print('  - Destination Title: $amt');
  }
  print("----------------------Background task is running");
}

3. 额外注意事项

  • 所有SharedPreferences的操作必须使用await,确保数据持久化完成后再通知服务;
  • 服务启动后,定时任务会每5秒自动读取最新数据,同时收到刷新消息会立即触发读取,保证数据实时性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 18:15:26