Flutter Drift 技能用于在 Flutter 应用中添加或修复基于 Drift 的本地持久化。它是一套操作工作流:先检查目标应用,只选择相关的参考文件,使用当前 Drift API 实现,并验证生成的代码。
核心工作流
编辑前先检查应用:查看 pubspec.yaml、现有数据库文件、build.yaml、状态管理包、目标平台和测试。优先沿用应用当前的架构和命名,而不是技能中的示例。
使用包命令添加或验证依赖,而不是硬编码版本:
dart pub add drift drift_flutter path_provider dev:drift_dev dev:build_runner
仅当应用已使用 provider 或 flutter_riverpod,或用户要求该集成时,才添加它们。
创建或更新数据库入口:在 Dart 或 .drift 文件中定义表;将表添加到 @DriftDatabase;除非项目需要自定义执行器,否则使用 package:drift_flutter/drift_flutter.dart 中的 driftDatabase 打开 Flutter 数据库。
将 Drift 调用限定在数据库对象上:在 widget、service 和 repository 中使用 database.select(database.todoItems)、database.into(database.todoItems)、database.update(database.todoItems) 和 database.delete(database.todoItems)。仅在 GeneratedDatabase 子类或 DatabaseAccessor 类中,当方法和表 getter 在作用域内时,才使用裸 select(todoItems)。
更改 Drift 声明后生成代码:运行 dart run build_runner build。将生成器错误视为阻塞项,而非可选的清理工作。
对于现有应用中的模式变更,使用 Drift 的引导式迁移工作流:在 build.yaml 中配置 drift_dev databases;根据需要在模式变更前后运行 dart run drift_dev make-migrations;提升 schemaVersion,编写生成的逐步迁移,并运行生成的迁移测试。
完成前验证:对编辑过的 Dart 文件运行 dart format;对包运行 flutter analyze 或 dart analyze;运行针对性测试,包括迁移变更时的生成迁移测试。
资源路由
添加 Drift、打开数据库、配置 Web 支持或跨 isolate 共享数据库时,阅读 references/setup.md。
定义表、列、默认值、键、索引、约束、生成列或严格表时,阅读 references/tables.md。
实现选择、过滤、排序、分页、连接、聚合、子查询、自定义列或联合时,阅读 references/queries.md。
实现插入、更新、删除、upsert、companion、事务或批量操作时,阅读 references/writes.md。
实现响应式 Drift 流、StreamBuilder、StreamProvider、自定义选择流、表更新监听器或手动流失效时,阅读 references/streams.md。
涉及 schemaVersion、现有用户数据、build.yaml、make-migrations、生成的模式文件或迁移测试时,阅读 references/migrations.md。
使用 Provider、Riverpod、StreamBuilder、搜索、过滤、分页或面向用户的加载和错误状态将 Drift 数据接入 Flutter widget 时,阅读 references/flutter-ui.md。
必需的 API 规则
不要从 widget 中将 select(database.table) 作为顶层函数调用。在数据库类之外使用 database.select(database.table)。
不要使用 watch(...)、todoUpdates(...) 或 notifyTableUpdates(...)。使用 customSelect(...).watch()、tableUpdates(...) 和 notifyUpdates(...)。
不要调用 delete(table).go(id)。添加 where 子句后调用 go(),或使用项目已使用的生成表扩展辅助方法。
不要使用 batch.updateAll(...) 或向 batch.delete(...) 传递原始 id。使用 batch.update(..., where: ...)、带可插入行的 batch.delete(...) 或 batch.deleteWhere(...)。
不要混用 Provider 和 Riverpod API。Provider.of<AppDatabase>(context) 属于 provider;Provider<AppDatabase>((ref) { ... }) 和 AsyncValue.when(...) 属于 Riverpod。
不要在没有针对现有数据库的迁移计划的情况下提升 schemaVersion。
当 UI 流必须更新时,不要依赖原始 SQLite 写入。使用 Drift 写入 API 或使用显式 TableUpdate 元数据调用 notifyUpdates。
回退方案
如果包下载被阻止,更新源文件并留下确切的 dart pub add 或 flutter pub add 命令给用户,然后说明依赖解析未经验证。
如果项目无法运行 build_runner,不要手写生成的 *.g.dart 文件。修复源声明并报告生成器阻塞。
如果迁移状态不明确,在更改 schemaVersion 之前停止;询问当前已发布的模式历史或数据库文件。
如果需要 Web 支持但缺少 sqlite3.wasm 和 drift_worker.js,添加代码路径并明确报告所需的 Web 资源。
验证清单
pubspec.yaml 包含 Drift 运行时和生成器依赖。
数据库文件具有有效的 part 指令、表声明、@DriftDatabase、构造函数和 schemaVersion。
所有查询和写入示例都限定在正确的数据库/访问器上下文中。
生成的代码已使用 build_runner 重新构建。
Flutter UI 示例处理加载、空、错误和数据状态,而不将 AsyncValue 当作 List。
迁移仅在具有生成的模式快照、逐步迁移代码和测试时更改。
flutter analyze 或 dart analyze 对编辑过的包通过,或报告任何剩余的 analyzer 失败及其阻塞原因。