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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 23:20:39