如何为SQFLite的User模型创建Stream适配StreamProvider监听数据变更?
SQFLite数据变更监听实现方案
SQFLite本身没有内置的数据变更监听机制,想要实现类似Firebase的StreamProvider效果,核心思路是用StreamController手动管理数据流——每次执行增删改操作后,主动拉取最新数据并推送到流中,外部通过监听这个流获取变更通知。
1. 定义User模型
先把User模型和数据库的序列化逻辑写好:
class User { final int id; final String name; User({required this.id, required this.name}); // 从数据库查询结果转模型 factory User.fromMap(Map<String, dynamic> map) { return User( id: map['id'], name: map['name'], ); } // 模型转数据库存储的Map Map<String, dynamic> toMap() { return { 'id': id, 'name': name, }; } }
2. 封装带监听的数据库操作类
把数据库初始化、增删改查和Stream管理封装到一个单例类里,确保全局只有一个数据源和流实例:
import 'package:sqflite/sqflite.dart'; import 'dart:async'; class UserDatabase { // 单例模式,避免重复初始化 static final UserDatabase _instance = UserDatabase._internal(); factory UserDatabase() => _instance; UserDatabase._internal(); Database? _db; // 用broadcast类型的StreamController,支持多订阅者 final StreamController<List<User>> _userStreamController = StreamController<List<User>>.broadcast(); // 初始化数据库 Future<void> init() async { _db = await openDatabase( 'users.db', version: 1, onCreate: (db, version) async { await db.execute(''' CREATE TABLE users( id INTEGER PRIMARY KEY, name TEXT ) '''); }, ); // 初始化时主动推送一次当前数据 await _refreshUserStream(); } // 私有方法:拉取最新用户数据并推送到流里 Future<void> _refreshUserStream() async { final users = await _getAllUsers(); _userStreamController.add(users); } // 对外暴露的用户数据Stream,供外部监听 Stream<List<User>> get userStream => _userStreamController.stream; // 数据库操作:获取所有用户 Future<List<User>> _getAllUsers() async { final mapList = await _db!.query('users'); return mapList.map((map) => User.fromMap(map)).toList(); } // 新增用户 Future<void> addUser(User user) async { await _db!.insert('users', user.toMap()); await _refreshUserStream(); // 操作完成后刷新流 } // 删除用户(你的初期需求) Future<void> deleteUser(int userId) async { await _db!.delete('users', where: 'id = ?', whereArgs: [userId]); await _refreshUserStream(); // 删除后推送最新数据 } // 更新用户(后续扩展需求) Future<void> updateUser(User user) async { await _db!.update('users', user.toMap(), where: 'id = ?', whereArgs: [user.id]); await _refreshUserStream(); // 更新后刷新流 } // 记得在应用退出时关闭资源 void dispose() { _userStreamController.close(); _db?.close(); } }
3. 在UI中监听数据变更
用Flutter自带的StreamBuilder来监听流,自动刷新UI:
StreamBuilder<List<User>>( stream: UserDatabase().userStream, initialData: const [], // 初始空数据 builder: (context, snapshot) { if (snapshot.hasData) { final users = snapshot.data!; return ListView.builder( itemCount: users.length, itemBuilder: (context, index) { final user = users[index]; return ListTile( title: Text(user.name), trailing: IconButton( icon: const Icon(Icons.delete), onPressed: () async { // 触发删除操作,流会自动推送更新 await UserDatabase().deleteUser(user.id); }, ), ); }, ); } // 加载状态 return const Center(child: CircularProgressIndicator()); }, )
4. 扩展到全量数据变更监听
如果后续要监听所有表的变更,可以升级成通用方案:
- 新增一个全局的
StreamController<void>,用来发送通用变更通知 - 所有数据库增删改操作完成后,都调用这个全局控制器的
add(null) - 各个业务模型的Stream监听这个全局通知,收到通知后自行拉取最新数据
这样不管哪个表发生变更,对应的业务流都会自动刷新。
内容的提问来源于stack exchange,提问作者MinisX
相关产品推荐
相关产品推荐

