You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何基于时间戳对比实现Flutter/Supabase实时数据变更流?

Flutter 实时获取required_by大于当前时间的记录流配置方案

一、Firebase Firestore(云端实时数据库)

Firestore原生支持实时数据监听,直接通过查询条件+快照流即可实现需求:

  1. 依赖配置
    确保pubspec.yaml中引入Cloud Firestore包:
dependencies:
  flutter:
    sdk: flutter
  cloud_firestore: ^4.17.1 # 替换为最新版本
  1. 构建实时查询流
    通过where过滤required_by大于当前时间,调用snapshots()获取实时更新:
import 'package:cloud_firestore/cloud_firestore.dart';

Stream<List<Map<String, dynamic>>> getActiveRecordsStream() {
  final currentTimestamp = Timestamp.now();
  return FirebaseFirestore.instance
      .collection('your_collection_name') // 替换为你的集合名
      .where('required_by', isGreaterThan: currentTimestamp)
      .snapshots()
      .map((snapshot) => snapshot.docs.map((doc) => doc.data()).toList());
}
  1. UI中使用流
    StreamBuilder监听流并渲染列表:
StreamBuilder<List<Map<String, dynamic>>>(
  stream: getActiveRecordsStream(),
  builder: (context, snapshot) {
    if (snapshot.hasError) return Text('加载出错: ${snapshot.error}');
    if (!snapshot.hasData) return const CircularProgressIndicator();
    
    final records = snapshot.data!;
    return ListView.builder(
      itemCount: records.length,
      itemBuilder: (context, index) {
        final record = records[index];
        return ListTile(
          title: Text(record['title'] ?? '无标题'),
          subtitle: Text('截止时间: ${record['required_by'].toDate()}'),
        );
      },
    );
  },
)

注意:required_by字段需存储为Firestore的Timestamp类型,避免用字符串或普通数字导致对比逻辑出错。

二、本地SQLite数据库

SQLite无原生实时监听,需结合StreamController手动实现:

  1. 依赖配置
dependencies:
  flutter:
    sdk: flutter
  sqflite: ^2.3.2
  path_provider: ^2.1.2
  1. 实现实时查询流
    通过定时查询触发流更新:
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:async';

class LocalDatabase {
  static Database? _db;
  final StreamController<List<Map<String, dynamic>>> _streamController = StreamController.broadcast();
  Timer? _queryTimer;

  Future<Database> get db async {
    if (_db != null) return _db!;
    _db = await _initDB();
    _startRealtimeQuery();
    return _db!;
  }

  Future<Database> _initDB() async {
    final dir = await getApplicationDocumentsDirectory();
    final path = '${dir.path}/your_db.db';
    return await openDatabase(
      path,
      version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE records(
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            title TEXT,
            required_by INTEGER -- 存储毫秒级时间戳
          )
        ''');
      },
    );
  }

  void _startRealtimeQuery() {
    // 每30秒查询一次,可根据需求调整间隔
    _queryTimer = Timer.periodic(const Duration(seconds: 30), (timer) async {
      final currentTime = DateTime.now().millisecondsSinceEpoch;
      final db = await this.db;
      final records = await db.query(
        'records',
        where: 'required_by > ?',
        whereArgs: [currentTime],
      );
      _streamController.add(records);
    });
    _fetchAndUpdateStream(); // 首次查询初始化数据
  }

  Future<void> _fetchAndUpdateStream() async {
    final currentTime = DateTime.now().millisecondsSinceEpoch;
    final db = await this.db;
    final records = await db.query(
      'records',
      where: 'required_by > ?',
      whereArgs: [currentTime],
    );
    _streamController.add(records);
  }

  Stream<List<Map<String, dynamic>>> getActiveRecordsStream() => _streamController.stream;

  // 页面销毁时关闭资源
  void dispose() {
    _queryTimer?.cancel();
    _streamController.close();
  }
}
  1. UI使用方式与Firestore一致,通过StreamBuilder监听流即可。

三、Realm数据库(移动端实时本地数据库)

Realm原生支持实时对象监听,配置更简洁:

  1. 依赖配置
dependencies:
  flutter:
    sdk: flutter
  realm: ^1.17.0
  1. 定义数据模型
import 'package:realm/realm.dart';

part 'record.g.dart';

@RealmModel()
class _Record {
  @PrimaryKey()
  late ObjectId id;
  late String title;
  late DateTime required_by;
}

运行flutter pub run realm generate生成模型代码。

  1. 构建实时流
import 'package:realm/realm.dart';

Stream<List<Record>> getActiveRecordsStream() {
  final realm = Realm(Configuration.local([Record.schema]));
  final currentTime = DateTime.now();
  return realm.all<Record>()
      .query('required_by > \$0', [currentTime])
      .changes
      .map((change) => change.results.toList());
}

使用时通过StreamBuilder渲染UI,注意管理Realm实例生命周期避免内存泄漏。


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

火山引擎 最新活动