如何基于时间戳对比实现Flutter/Supabase实时数据变更流?
Flutter 实时获取
required_by大于当前时间的记录流配置方案 一、Firebase Firestore(云端实时数据库)
Firestore原生支持实时数据监听,直接通过查询条件+快照流即可实现需求:
- 依赖配置
确保pubspec.yaml中引入Cloud Firestore包:
dependencies: flutter: sdk: flutter cloud_firestore: ^4.17.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()); }
- 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手动实现:
- 依赖配置
dependencies: flutter: sdk: flutter sqflite: ^2.3.2 path_provider: ^2.1.2
- 实现实时查询流
通过定时查询触发流更新:
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(); } }
- UI使用方式与Firestore一致,通过
StreamBuilder监听流即可。
三、Realm数据库(移动端实时本地数据库)
Realm原生支持实时对象监听,配置更简洁:
- 依赖配置
dependencies: flutter: sdk: flutter realm: ^1.17.0
- 定义数据模型
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生成模型代码。
- 构建实时流
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




