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

Flutter中Stream.periodic能否跳过事件?示例写法是否最优?

问题解答

1. Stream.periodic中避免分发事件的可行性

可以实现。你当前的做法是在Stream.periodic的生成函数中返回null,再通过外层的await for过滤掉null值来避免无效事件分发,这是一种可行的方式。不过还有更简洁的实现思路:直接通过自定义异步生成器(async*)来控制事件的发射,不需要依赖Stream.periodic生成多余的null事件。

2. 当前RiverPod实现的优化空间

你的实现可以正常工作,但存在几个可以优化的点:

  • 不必要的IO操作:每分钟都会写入SharedPreferences,哪怕日期没有变化,频繁的本地存储操作会浪费资源
  • 冗余的事件过滤:Stream.periodic每次都会生成事件(哪怕是null),再在外层过滤,增加了不必要的事件流转
  • 初始逻辑缺失:首次运行时,因为没有历史时间戳,不会触发事件,如果需要首次启动就检测是否是新的一天(比如APP跨天启动),当前逻辑无法覆盖

优化后的实现方案

final newDayProvider = StreamProvider<DateTime>((ref) async* {
  const dayCheckerKey = 'dayCheckerTimestamp';
  final sharedPrefs = ref.read(sharedPrefsProvider);
  
  // 首次启动先检查是否跨天
  final lastTimestampStr = sharedPrefs.getString(dayCheckerKey);
  final now = DateTime.now();
  final today = DateTime(now.year, now.month, now.day);
  
  if (lastTimestampStr != null) {
    final lastDay = DateTime.parse(lastTimestampStr);
    final lastCheckDay = DateTime(lastDay.year, lastDay.month, lastDay.day);
    if (lastCheckDay.isBefore(today)) {
      yield today;
      sharedPrefs.setString(dayCheckerKey, now.toIso8601String());
    }
  } else {
    // 首次运行,记录当前日期
    sharedPrefs.setString(dayCheckerKey, now.toIso8601String());
  }

  // 定时检查日期变化
  while (true) {
    await Future.delayed(const Duration(minutes: 1));
    final currentNow = DateTime.now();
    final currentDay = DateTime(currentNow.year, currentNow.month, currentNow.day);
    
    final latestTimestampStr = sharedPrefs.getString(dayCheckerKey);
    if (latestTimestampStr == null) continue;
    
    final lastCheckDay = DateTime.parse(latestTimestampStr);
    final lastDay = DateTime(lastCheckDay.year, lastCheckDay.month, lastCheckDay.day);
    
    if (lastDay.isBefore(currentDay)) {
      yield currentDay;
      sharedPrefs.setString(dayCheckerKey, currentNow.toIso8601String());
    }
  }
});

优化点说明

  • 减少IO操作:只有当日期确实变化时,才更新SharedPreferences
  • 精准控制事件:通过while(true) + Future.delayed替代Stream.periodic,只在需要时发射事件,避免冗余的null事件
  • 补充初始检查:APP启动时先判断是否跨天,覆盖了跨天启动的场景
  • 日期比较更严谨:通过提取年/月/日创建纯日期对象进行比较,避免时分秒干扰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 11:35:05