**在 Flutter 项目中引入并使用 ObjectBox **
ObjectBox 是一个高性能的 NoSQL 数据库,专为嵌入式场景(如移动端和桌面应用)设计,具有高效的增删查改能力,适合需要本地数据存储的 Flutter 项目。
1. 环境准备
1.1 安装依赖
在 pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
objectbox: ^1.7.0
objectbox_flutter_libs: ^1.7.0 # 针对移动平台使用的库
dev_dependencies:
build_runner: ^2.4.6 # 用于代码生成
objectbox_generator: ^1.7.0
运行以下命令安装依赖:
flutter pub get
2. 创建实体类
使用 @Entity()
注解定义需要存储的数据模型。每个实体类必须有一个 int
类型的 ID 字段,并且不能是 final
,以便 ObjectBox 能自动生成或管理主键。
示例:用户实体类
import 'package:objectbox/objectbox.dart';
@Entity()
class User {
int id = 0; // 主键,由 ObjectBox 自动生成
final String username;
final String passwordHash;
final String? phone;
final String? email;
final String? avatarUrl;
@Property(type: PropertyType.date) // 指定日期存储精度为毫秒
final DateTime createdAt;
@Property(type: PropertyType.date) // 指定日期存储精度为毫秒
final DateTime updatedAt;
User({
required this.username,
required this.passwordHash,
this.phone,
this.email,
this.avatarUrl,
required this.createdAt,
required this.updatedAt,
});
}
3. 生成代码
ObjectBox 使用 build_runner
工具自动生成数据交互代码。生成的文件会包含实体类的元信息和增删查改的操作逻辑。
在项目根目录运行以下命令:
dart run build_runner build
生成的文件通常为:
objectbox.g.dart
:主数据库交互文件。
如果需要清理构建缓存,可以运行:
dart run build_runner clean
4. 初始化 ObjectBox
在应用启动时,需要初始化 ObjectBox 数据库。
步骤:
- 使用
getApplicationDocumentsDirectory()
获取存储路径。 - 调用
openStore()
方法初始化数据库。
代码示例:
import 'package:flutter/material.dart';
import 'package:objectbox/objectbox.dart';
import 'package:path_provider/path_provider.dart';
late final Store store; // 全局数据库实例
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// 获取存储目录并初始化 ObjectBox
final directory = await getApplicationDocumentsDirectory();
store = await openStore(directory: directory.path);
runApp(MyApp());
}
5. 数据操作
ObjectBox 提供了一组简单高效的操作方法,包括增、删、查、改。以下是详细示例:
5.1 插入数据
通过 Box
对象的 put()
方法插入或更新数据。
final user = User(
username: 'JohnDoe',
passwordHash: 'hashed_password',
phone: '123456789',
email: '[email protected]',
avatarUrl: 'https://example.com/avatar.png',
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
);
final box = store.box<User>();
box.put(user); // 插入或更新数据
5.2 查询数据
查询所有数据
使用 getAll()
方法获取所有实体:
final box = store.box<User>();
final users = box.getAll(); // 获取所有用户
for (var user in users) {
print('User: ${user.username}, Created At: ${user.createdAt}');
}
条件查询
通过 query()
方法创建查询语句:
final query = box.query(User_.username.equals('JohnDoe')).build();
final results = query.find(); // 查询结果
query.close(); // 查询完成后释放资源
分页查询
通过 offset
和 limit
分页加载:
final results = box.query().build().find(limit: 10, offset: 20);
5.3 更新数据
通过 put()
方法更新数据:
final user = box.get(1); // 获取 ID 为 1 的用户
if (user != null) {
user.email = '[email protected]';
box.put(user); // 更新数据
}
5.4 删除数据
根据 ID 删除
box.remove(1); // 删除 ID 为 1 的用户
删除所有数据
box.removeAll(); // 删除所有用户
6. 关系型数据
ObjectBox 支持一对一、一对多、多对多的关系存储。
一对多关系示例
@Entity()
class Author {
int id = 0;
String name;
@Backlink('author') // 反向关系
final books = ToMany<Book>();
Author({required this.name});
}
@Entity()
class Book {
int id = 0;
String title;
final author = ToOne<Author>(); // 引用 Author
Book({required this.title});
}
插入和查询:
final author = Author(name: 'Author Name');
final book1 = Book(title: 'Book One')..author.target = author;
final book2 = Book(title: 'Book Two')..author.target = author;
final authorBox = store.box<Author>();
final bookBox = store.box<Book>();
authorBox.put(author); // 插入作者
bookBox.putMany([book1, book2]); // 插入书籍
// 查询作者的书籍
final retrievedAuthor = authorBox.get(author.id)!;
print(retrievedAuthor.books.map((book) => book.title).toList());
7. 数据持久化和安全性
- ObjectBox 默认将数据存储在应用的私有目录中,路径由
path_provider
提供,其他应用无法访问。 - 关机或断电数据安全性:ObjectBox 使用事务机制,确保所有写入操作是原子性的,即使发生崩溃或断电,数据仍然一致。
- 加密支持:可以手动对敏感数据字段进行加密,例如使用
encrypt
包。
8. 清理资源
为了避免资源泄露,在不需要时可以关闭数据库:
store.close();
9. 常见问题
9.1 运行 build_runner
报错
- 确保
pubspec.yaml
中正确添加了build_runner
和objectbox_generator
。 - 运行以下命令清理构建缓存:
dart run build_runner clean dart run build_runner build
9.2 时间字段警告
如果使用 DateTime
字段,请明确指定存储类型为 @Property(type: PropertyType.date)
。
10. 适用场景
- 本地消息存储(如聊天应用)。
- 离线优先的业务逻辑(如电商订单缓存)。
- 快速的数据查询和处理(如联系人管理)。
评论区