Flutter 每周重复本地通知仅当日生效 代码异常问题求助
Flutter 每周重复本地通知异常修复方案
你的代码存在两个核心问题导致非当日通知无法触发:
- 时间计算逻辑存在边界漏洞:
_scheduleWeekly方法依赖_scheduleDaily的返回值做累加,当指定的通知时间在今日已过、且目标weekday早于当前weekday时,循环累加的方式在部分时区场景下会出现偏移误差。 - 未校验weekday取值规范:Dart内置
DateTime.weekday属性的取值规则为周一=1、周日=7,如果你的业务侧传入的weekday是按周日=1、周六=7的规则计算,会导致匹配失败,永远找不到符合条件的触发日期。
修复后完整代码
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/timezone.dart' as tz; import 'package:timezone/data/latest_all.dart' as tz; // 应用启动时必须先初始化时区,不要漏掉这步 void initTimeZone() { tz.initializeTimeZones(); tz.setLocalLocation(tz.getLocation('Asia/Shanghai')); // 替换为对应地区时区 } static Future showWeeklyNotification({ required int id, String? title, String? body, String? payload, required int weekday, // 必须符合Dart规范:1=周一, 7=周日 required Time scheduleTime, }) async => _notifications.zonedSchedule( id, title, body, _scheduleWeekly(scheduleTime, weekday), await _notificationDetails(), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: DateTimeComponents.dayOfWeekAndTime, ); static tz.TZDateTime _scheduleDaily(Time time) { final now = tz.TZDateTime.now(tz.local); final scheduleDate = tz.TZDateTime(tz.local, now.year, now.month, now.day, time.hour, time.minute, time.second); return scheduleDate.isBefore(now) ? scheduleDate.add(const Duration(days: 1)) : scheduleDate; } // 优化后的周时间计算逻辑,用取模运算替代循环累加,避免边界误差 static tz.TZDateTime _scheduleWeekly(Time time, int weekday) { var scheduleDate = _scheduleDaily(time); int daysToAdd = (weekday - scheduleDate.weekday + 7) % 7; scheduleDate = scheduleDate.add(Duration(days: daysToAdd)); return scheduleDate; }
注意事项
- 每个不同的通知必须分配唯一ID,比如周一的3个不同时间的通知需要对应3个不同ID,否则新通知会覆盖同ID的旧通知。
- 安卓端需要确保通知权限、后台弹出通知权限、自启动权限已开启,部分国产系统限制严格,未开权限会导致息屏/后台状态收不到通知。
- 如果你的业务逻辑里周日是一周第一天,传入的weekday为1代表周日,需要提前做转换再传参:
int dartWeekday = businessWeekday == 1 ? 7 : businessWeekday -1;
内容的提问来源于stack exchange,提问作者Sushant
相关产品推荐
相关产品推荐

