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

Flutter实现每日9-17点随机内容定时离线通知的方案咨询

解决Flutter本地定时通知的两个核心问题

问题1:重复通知内容固定,无法随机生成

根源在于调用zonedSchedule时,通知内容就被固化存储了,后续重复触发不会重新执行NotificationRepo.getNotification方法获取新内容。

直接调整逻辑:放弃一次性设置重复通知,改成每次通知触发后,动态生成下一次的内容并调度:

  • 初始只调度当天第一个待触发的通知(比如9:00),此时调用随机内容方法生成内容。
  • 监听通知触发的回调(onDidReceiveLocalNotification),每次触发后计算下一个小时的时间,若在9:00-17:00范围内,就调用zonedSchedule调度下一条通知,同时传入新的随机内容。
  • 当天17:00的通知触发后,自动调度次日9:00的通知。

问题2:64条通知上限,无法提前数周排期

一次性提前排期会占用大量通知名额,直接用滚动调度解决:只保留当前待触发的1条通知,每次触发后再调度下一个,永远不会触及64条上限。

同时配合后台任务插件(如workmanager),在应用被杀死或设备重启后,自动在每天8:50左右触发任务,重新调度当天的通知,确保离线场景不中断。


具体代码示例

1. 初始调度逻辑

void scheduleDailyNotifications() async {
  final now = DateTime.now();
  DateTime nextNotificationTime;

  // 确定当天第一个待触发的时间
  if (now.hour < 9) {
    nextNotificationTime = DateTime(now.year, now.month, now.day, 9);
  } else if (now.hour >= 17) {
    nextNotificationTime = DateTime(now.year, now.month, now.day + 1, 9);
  } else {
    // 取当前小时的下一个整点
    nextNotificationTime = DateTime(now.year, now.month, now.day, now.hour + 1);
  }

  await _scheduleSingleNotification(nextNotificationTime);
}

Future<void> _scheduleSingleNotification(DateTime scheduledTime) async {
  // 每次调度时才生成随机内容
  final notificationContent = NotificationRepo.getNotification(notification.category);
  await flutterLocalNotificationsPlugin.zonedSchedule(
    0, // 复用同一个ID,覆盖之前的待调度通知
    "Promise",
    notificationContent,
    tz.TZDateTime.from(scheduledTime, tz.local),
    notificationDetails,
    androidAllowWhileIdle: true,
    uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
    // 不设置重复,手动控制下一次调度
    matchDateTimeComponents: null,
  );
}

2. 监听通知触发并滚动调度

// 初始化插件时绑定回调
flutterLocalNotificationsPlugin.initialize(
  InitializationSettings(
    android: AndroidInitializationSettings('@mipmap/ic_launcher'),
    iOS: IOSInitializationSettings(),
  ),
  onDidReceiveLocalNotification: (id, title, body, payload) async {
    // 通知触发后立刻调度下一条
    await _scheduleNextNotification();
  },
);

Future<void> _scheduleNextNotification() async {
  final now = DateTime.now();
  DateTime nextTime;

  if (now.hour >= 9 && now.hour < 17) {
    nextTime = DateTime(now.year, now.month, now.day, now.hour + 1);
  } else {
    // 当天时段结束,调度次日9点的通知
    nextTime = DateTime(now.year, now.month, now.day + 1, 9);
  }

  await _scheduleSingleNotification(nextTime);
}

3. 后台任务保障(避免应用被杀中断)

用workmanager设置每日定时任务,确保设备重启或应用被杀后,调度逻辑自动恢复:

void initializeWorkManager() async {
  await Workmanager().initialize(
    callbackDispatcher,
    isInDebugMode: false,
  );
  // 每天8:50执行一次调度任务
  await Workmanager().registerPeriodicTask(
    'daily-notification-scheduler',
    'schedule-notifications',
    frequency: Duration(days: 1),
    initialDelay: _getDelayToTargetTime(8, 50),
  );
}

Duration _getDelayToTargetTime(int hour, int minute) {
  final now = DateTime.now();
  final target = DateTime(now.year, now.month, now.day, hour, minute);
  return now.isAfter(target) 
      ? target.add(Duration(days: 1)).difference(now) 
      : target.difference(now);
}

// 后台回调函数
void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    if (task == 'schedule-notifications') {
      await scheduleDailyNotifications();
    }
    return Future.value(true);
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 02:17:32