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

如何用Flutter Local Notifications实现28天周期规律通知?

可行性分析与实现方案

完全可行,借助Flutter Local Notifications插件的自定义调度能力,结合日期计算和本地存储,就能实现这种分段循环的周期通知功能。

核心逻辑

  • 以28天为一个循环周期,用户设置X后,前X天按固定时段发送通知,剩余28-X天静默
  • 每个周期结束后自动触发重置,从第1天开始新一轮循环

具体实现步骤

1. 初始化通知插件

先完成插件的基础初始化(Android/iOS的原生配置按官方要求完成即可,以下是Dart层代码):

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:shared_preferences/shared_preferences.dart';

final FlutterLocalNotificationsPlugin _notificationsPlugin =
    FlutterLocalNotificationsPlugin();

Future<void> initNotifications() async {
  const AndroidInitializationSettings androidSettings =
      AndroidInitializationSettings('@mipmap/ic_launcher');
  const DarwinInitializationSettings iosSettings = DarwinInitializationSettings();
  const InitializationSettings initSettings = InitializationSettings(
    android: androidSettings,
    iOS: iosSettings,
  );

  // 设置通知回调,处理周期重置
  await _notificationsPlugin.initialize(
    initSettings,
    onDidReceiveNotificationResponse: (response) async {
      if (response.payload == 'reset_cycle') {
        final int userX = await _getUserX();
        await _scheduleCycleNotifications(userX);
      }
    },
  );
}

2. 调度周期内的通知

实现核心的通知调度函数,负责生成一个28天周期内的所有通知,并添加周期重置触发点:

// 调度一个完整周期的通知,X为用户设置的通知天数
Future<void> _scheduleCycleNotifications(int X) async {
  // 先清空旧通知,避免重复
  await _notificationsPlugin.cancelAll();

  final DateTime now = DateTime.now();
  // 遍历28天,只在前X天安排通知
  for (int dayOffset = 0; dayOffset < 28; dayOffset++) {
    if (dayOffset >= X) continue;

    // 设置每天固定发送时间,比如早上8点
    DateTime scheduledTime = DateTime(
      now.year,
      now.month,
      now.day + dayOffset,
      8,
      0,
    );

    // 如果当天的发送时间已过,顺延到次日
    if (scheduledTime.isBefore(now)) {
      scheduledTime = scheduledTime.add(const Duration(days: 1));
    }

    await _notificationsPlugin.schedule(
      dayOffset, // 用天数偏移量作为通知ID,避免重复
      '周期提醒',
      '这是第${dayOffset + 1}天的通知',
      scheduledTime,
      const NotificationDetails(
        android: AndroidNotificationDetails(
          'cycle_notif_channel',
          '周期通知频道',
          importance: Importance.max,
          priority: Priority.high,
        ),
        iOS: DarwinNotificationDetails(),
      ),
      payload: 'day_${dayOffset + 1}',
    );
  }

  // 添加周期重置触发通知(静默,不打扰用户)
  final DateTime resetTime = now.add(const Duration(days: 28));
  await _notificationsPlugin.schedule(
    999, // 专属重置ID
    '',
    '',
    resetTime,
    const NotificationDetails(
      android: AndroidNotificationDetails(
        'reset_channel',
        '周期重置频道',
        importance: Importance.low,
        priority: Priority.low,
        enableVibration: false,
        enableSound: false,
      ),
      iOS: DarwinNotificationDetails(
        presentAlert: false,
        presentSound: false,
      ),
    ),
    payload: 'reset_cycle',
  );
}

3. 处理用户设置与App重启

  • 用SharedPreferences存储用户设置的X值,默认28天
  • App启动时检查当前周期进度,重新调度未发送的通知:
// 获取用户设置的X值,默认28
Future<int> _getUserX() async {
  final prefs = await SharedPreferences.getInstance();
  return prefs.getInt('notification_cycle_x') ?? 28;
}

// 保存用户修改的X值并重新调度通知
Future<void> updateUserX(int newX) async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setInt('notification_cycle_x', newX);
  await _scheduleCycleNotifications(newX);
}

// App启动时调用,恢复通知调度
Future<void> restoreNotifications() async {
  final int userX = await _getUserX();
  await _scheduleCycleNotifications(userX);
}

关键注意点

  • iOS权限:需要在Info.plist中添加UIBackgroundModes并包含remote-notification,否则本地通知的后台触发可能失效
  • 设备重启:本地通知在设备重启后会丢失,建议在initState或App启动时调用restoreNotifications恢复调度
  • 静默通知:重置用的通知要设置为无提示,避免干扰用户

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 16:05:25