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

Flutter中为列表项后台管理Timer实现自动移除功能

Flutter 后台自动移除通知条目解决方案

核心思路

用可监听的状态管理器统一处理列表维护和Timer逻辑,确保Timer在后台独立运行,同时通过状态通知让对话框实时同步列表状态。


1. 封装通知管理器

创建NotificationManager类,负责条目添加、自动移除以及状态通知:

import 'dart:async';
import 'package:flutter/foundation.dart';

class NotificationManager extends ChangeNotifier {
  final List<NotificationItem> _notificationItems = [];
  final Set<Timer> _activeTimers = {};

  // 对外暴露不可修改的列表,避免外部直接篡改
  List<NotificationItem> get items => List.unmodifiable(_notificationItems);

  // 添加新条目并启动过期Timer
  void addNotification(NotificationItem item) {
    _notificationItems.add(item);
    notifyListeners();

    // 1分钟后自动移除
    final timer = Timer(const Duration(minutes: 1), () {
      _removeNotification(item.id);
      _activeTimers.remove(timer);
    });
    _activeTimers.add(timer);
  }

  // 内部移除条目并通知更新
  void _removeNotification(String itemId) {
    _notificationItems.removeWhere((item) => item.id == itemId);
    notifyListeners();
  }

  // 销毁时清理所有Timer,防止内存泄漏
  @override
  void dispose() {
    for (final timer in _activeTimers) {
      timer.cancel();
    }
    _activeTimers.clear();
    super.dispose();
  }
}

// 通知条目模型,必须带唯一ID用于精准移除
class NotificationItem {
  final String id;
  final String content;

  NotificationItem({required this.id, required this.content});
}

2. 注入管理器到Widget树

把NotificationManager放到页面层级,确保Socket回调和对话框能访问同一个实例:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => NotificationManager(),
      child: Scaffold(
        appBar: AppBar(title: const Text('通知测试')),
        floatingActionButton: FloatingActionButton(
          onPressed: () => _showNotificationDialog(context),
          child: const Icon(Icons.notifications),
        ),
        // 你的其他页面内容
      ),
    );
  }
}

3. 实现动态更新的对话框

对话框通过Consumer监听管理器状态变化,后台移除条目时也能实时刷新:

void _showNotificationDialog(BuildContext context) {
  showDialog(
    context: context,
    builder: (dialogContext) {
      return AlertDialog(
        title: const Text('最新通知'),
        content: Consumer<NotificationManager>(
          builder: (_, manager, __) {
            if (manager.items.isEmpty) {
              return const Text('暂无新通知');
            }
            return ListView.builder(
              shrinkWrap: true,
              itemCount: manager.items.length,
              itemBuilder: (_, index) {
                final item = manager.items[index];
                return ListTile(title: Text(item.content));
              },
            );
          },
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(dialogContext),
            child: const Text('关闭'),
          ),
        ],
      );
    },
  );
}

4. Socket回调中添加条目

在Socket接收到新通知时,获取管理器实例并添加条目:

// 假设你的Socket接收回调函数
void handleSocketMessage(Map<String, dynamic> message) {
  // listen设为false,避免不必要的监听重建
  final manager = Provider.of<NotificationManager>(context, listen: false);
  manager.addNotification(
    NotificationItem(
      id: DateTime.now().millisecondsSinceEpoch.toString(), // 用时间戳做唯一ID
      content: message['content'],
    ),
  );
}

关键注意事项

  • 内存泄漏防护:页面销毁时务必调用NotificationManager.dispose(),比如在StatefulWidget的dispose方法中:
    @override
    void dispose() {
      Provider.of<NotificationManager>(context, listen: false).dispose();
      super.dispose();
    }
    
  • 状态唯一性:所有列表操作必须通过NotificationManager完成,外部不能直接修改列表,保证状态一致。
  • 后台运行保障:Timer绑定在管理器上,和对话框生命周期无关,即使对话框关闭,Timer依然会在后台执行移除逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:15:36