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

Flutter Local Notification重复显示相同随机字符串问题求助

问题分析

你当前使用periodicallyShow方法时,是将**提前生成好的randomName**作为通知内容传入的——这个方法会一次性固定通知内容,后续重复推送的都是第一次传入的字符串,不会每次触发时重新执行随机逻辑,这就是为什么内容始终重复的原因。

解决方案

放弃periodicallyShow,改用单次通知+定时调度的方式,每次推送前生成新的不重复随机内容,并安排下一次通知。同时通过集合记录已推送内容,避免重复。

步骤1:添加依赖

需要引入时区处理依赖,用于精准调度每日通知:

dependencies:
  flutter_local_notifications: ^latest_version
  timezone: ^latest_version

步骤2:初始化时区

在main函数中初始化时区支持:

import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;

void main() async {
  tz.initializeTimeZones();
  runApp(const MyApp());
}

步骤3:重构通知服务类

import 'dart:math';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart' as tz;

class NotificationService {
  final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();
  final Set<String> _usedNames = {};
  // 替换成你的字符串列表
  final List<String> _names = ["内容1", "内容2", "内容3", "内容4", "内容5"];

  // 初始化通知配置
  Future<void> init() async {
    const AndroidInitializationSettings androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
    const DarwinInitializationSettings iosSettings = DarwinInitializationSettings();
    const InitializationSettings initSettings = InitializationSettings(android: androidSettings, iOS: iosSettings);
    
    await _notificationsPlugin.initialize(initSettings);
  }

  // 生成不重复的随机字符串
  String _getUniqueRandomName() {
    // 所有内容推完后重置记录
    if (_usedNames.length == _names.length) {
      _usedNames.clear();
    }

    String? selectedName;
    final random = Random();
    // 循环直到找到未推送过的内容
    do {
      selectedName = _names[random.nextInt(_names.length)];
    } while (_usedNames.contains(selectedName));

    _usedNames.add(selectedName!);
    return selectedName;
  }

  // 调度每日通知(含当前推送+次日调度)
  Future<void> scheduleDailyNotification(String title) async {
    // 生成当前要推送的内容
    final currentContent = _getUniqueRandomName();
    
    // 推送当前通知
    await _notificationsPlugin.show(
      1,
      title,
      currentContent,
      const NotificationDetails(
        android: AndroidNotificationDetails(
          'main_channel',
          'Main Channel',
          channelDescription: "日常通知",
          importance: Importance.max,
          priority: Priority.max,
        ),
        iOS: DarwinNotificationDetails(
          sound: 'default.wav',
          presentAlert: true,
          presentBadge: true,
          presentSound: true,
        ),
      ),
      androidAllowWhileIdle: true,
    );

    // 计算次日同一时间的推送点(这里设置为每天10点)
    var nextTime = tz.TZDateTime.now(tz.local).add(const Duration(days: 1));
    nextTime = tz.TZDateTime(
      tz.local,
      nextTime.year,
      nextTime.month,
      nextTime.day,
      10,
      0,
    );

    // 如果次日时间已过(比如当前是11点,设置的是10点),则延后到第三天
    if (nextTime.isBefore(tz.TZDateTime.now(tz.local))) {
      nextTime = nextTime.add(const Duration(days: 1));
    }

    // 调度下一次通知
    await _notificationsPlugin.zonedSchedule(
      1,
      title,
      _getUniqueRandomName(),
      nextTime,
      const NotificationDetails(
        android: AndroidNotificationDetails(
          'main_channel',
          'Main Channel',
          channelDescription: "日常通知",
          importance: Importance.max,
          priority: Priority.max,
        ),
        iOS: DarwinNotificationDetails(
          sound: 'default.wav',
          presentAlert: true,
          presentBadge: true,
          presentSound: true,
        ),
      ),
      androidAllowWhileIdle: true,
      uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
      matchDateTimeComponents: DateTimeComponents.time,
    );
  }
}

步骤4:按钮点击调用

onPressed: () async {
  setState(() {
    showToast();
  });
  final notificationService = NotificationService();
  await notificationService.init();
  await notificationService.scheduleDailyNotification('$randomNames${widget.userPost}');
},
关键说明
  1. 抛弃periodicallyShow:该方法是静态重复通知,内容无法动态更新,不适合需要随机内容的场景。
  2. 去重逻辑:通过Set记录已推送内容,确保每次推送的字符串唯一,所有内容推完后自动重置。
  3. 时区调度:使用zonedSchedule保证每日固定时间推送,避免因时区或日期变化导致的调度错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:35:20