Hive:是什么,NoSQL 存储与无需原生代码的开发

作者: IT Sectr 发布日期: 2026-03-13 阅读时间: 9 分钟

Hive — 一个适用于 Flutter 的轻量级 NoSQL 存储,无需原生代码即可运行。与 SQLite 或 Firebase 不同,Hive 不需要连接原生库,完全通过 Dart 运行。据 Pub.dev,2024 数据显示,Hive 已被下载超过 1000 万次,并且在每三个需要本地数据存储而无需服务器基础设施的 Flutter 项目中就有一个在使用它。

要点

  • Hive — 纯 Dart 的 NoSQL 数据库,无需原生代码和平台依赖
  • 性能 — 在移动设备上每秒高达 30,000 次读取
  • 类型化 — TypeAdapter 用于自定义对象,无需代码生成
  • 轻量 — 0 依赖 Android SDK 或 iOS UIKit
  • 响应式 — WatchBox 用于实时跟踪变更

什么是 Hive?

Hive — 是一个完全用 Dart 编写且不需要原生库的 NoSQL 数据库。它由 Simon Leiter 于 2019 年创建,作为 Flutter 项目中 SQLite 的替代方案。Hive 以二进制 .hive 格式存储数据,该格式针对移动设备上的快速读写进行了优化。.hive 格式使用自定义序列化方案,其中每种数据类型都有自己的字节前缀,允许在无需提前了解方案的情况下读取文件 — 这与 Protocol Buffers 或 FlatBuffers 不同。

Hive 的主要理念是极致简单。数据库不需要初始化原生引擎,不包含 SQL 解析器,也不使用反射。所有操作都是通过 WriteBufferReadBuffer 进行二进制序列化的直接 Dart 函数调用。

根据 Flutter Community(2023 年)的调查,Hive 是 Flutter 中数据存储使用量排名前 5 的软件包,在流行度上仅次于 shared_preferences,但在功能性和速度上超越它。

Hive 架构

Hive 使用 Box 概念 — 类似于关系数据库中的表。每个 Box 是磁盘上的一个文件,包含一组键值对。键可以是 int 或 String,值可以是任何基本类型、列表、Map 或通过 TypeAdapter 的自定义对象。Box 之间相互隔离并独立打开。

相比原生解决方案的优势

Hive 不需要平台通道(platform channels)。这意味着它在 Android、iOS、Web、macOS、Windows 和 Linux 上无需额外配置即可相同运行。对于面向 Web 编译的项目,Hive 仍然是唯一的轻量级 NoSQL 解决方案 — SQLite 在浏览器中无法运行。同时,Hive 使用 IndexedDB 作为 Web 的后端,确保在浏览器环境中数据的持久性。

Hive 如何工作?

Hive 在写入时将数据序列化为二进制格式,在读取时反序列化。内部机制基于 BinaryWriterBinaryReader,它们将数据打包成紧凑的字节数组。磁盘上的存储大小平均比相同数据的 JSON 表示小 2-3 倍。

打开 Box 时,Hive 将整个文件加载到 RAM 中。这提供了高速读取(微秒级),但限制了数据大小:建议每个 Box 存储不超过 50-100 MB。对于更大的数据量,请使用 LazyBox — 从磁盘延迟加载记录。

事务和并发

Hive 在 Dart isolate 隔离中单线程运行。写入操作通过文件锁定同步执行。对于异步访问,请使用带 await 的 Hive.openBox()。不支持直接从多个 isolate 并发访问 — 这需要单独的同步机制。

Hive vs SharedPreferences 和 vs SQLite

Hive 处于 SharedPreferences 和 SQLite 之间。它比 SharedPreferences 更复杂(支持自定义对象),但比 SQLite 更简单(不需要 SQL 查询)。让我们比较关键特性。

特性HiveSharedPreferencesSQLite
数据类型任何类型(通过 TypeAdapter)仅基本类型SQL 类型
读取速度~30,000 ops/s~5,000 ops/s~2,000 ops/s
原生代码不需要需要(Android)需要
Web 支持
复杂度最小中等
响应性WatchBox通过 ORM

何时选择 Hive

Hive 非常适合小数据量:应用程序设置、API 响应缓存、本地同步队列、收藏夹和浏览历史。如果数据不超过 50 MB 且不需要关系查询 — Hive 比 SQLite 更快更简单。

何时 Hive 不适合

Hive 不支持多字段过滤、JOIN、聚合函数等查询。如果您需要像 “选择今天所有优先级高于 3 的任务” 这样的复杂查询 — 请使用带 drift 或 floor 的 SQLite。由于加载到内存中,Hive 也不适合存储超过 100 MB 的数据。

Hive 代码示例

Hive 从初始化和打开 Box 开始。下面是典型场景的基本操作 — 在 Flutter 应用程序中存储任务列表。所有示例无需原生平台调用即可运行。

初始化和打开 Box

在使用 Hive 之前,需要在 main 函数中调用 Hive.initFlutter()。然后通过 Hive.openBox() 打开 Box — 结果将是一个准备好读写操作的 Box 实例。

dart
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';

void async main() {
    await Hive.initFlutter();
    final settingsBox = await Hive.openBox('settings');
    runApp(MyApp());
}

CRUD 操作

Box 提供 put、get、delete 方法,并包含遍历所有记录的迭代器。键和值通过泛型进行类型化 — 默认情况下 Box<dynamic> 允许任何类型,但建议指定具体类型。

dart
// 写入数据
final box = await Hive.openBox<String>('tasks');
await box.put('task_1', '购买商品');

// 读取
final task = box.get('task_1');

// 所有键
final allTasks = box.values.toList();

// 删除
await box.delete('task_1');

// 清空 Box
await box.clear();

通过 WatchBox 进行响应式观察

WatchBox — Box 的扩展,用于通知订阅者变更。在 Flutter 中,这与 ValueListenableBuilder 集成:当 Box 中任何值发生变化时,widget 会自动重建,无需调用 setState。

dart
final watchBox = await Hive.openBox('settings');

// 在 Widget 中
ValueListenableBuilder(
    valueListenable: watchBox.listenable(),
    builder: (context, box, _) {
        final counter = box.get('counter') ?? 0;
        return Text('计数器:$counter');
    },
)

TypeAdapter 和自定义对象

TypeAdapter — Hive 用于序列化自定义 Dart 对象的机制。适配器描述如何将对象转换为二进制格式(write)和恢复(read)。与 json_serializable 不同,TypeAdapter 不需要反射且运行更快。

创建 TypeAdapter

适配器实现具有两个方法 TypeAdapter 的接口:read 和 write。在打开 Box 之前通过 Hive.registerAdapter() 注册类。每个适配器分配一个数字 ID — 保存在文件中用于类型识别。

dart
// 数据模型
class Task {
    final String title;
    final bool isCompleted;
    Task({required this.title, this.isCompleted = false});
}

// TypeAdapter
class TaskAdapter extends TypeAdapter<Task> {
    @override
    final int typeId = 0;

    @override
    Task read(BinaryReader reader) {
        return Task(
            title: reader.readString(),
            isCompleted: reader.readBool(),
        );
    }

    @override
    void write(BinaryWriter writer, Task obj) {
        writer.writeString(obj.title);
        writer.writeBool(obj.isCompleted);
    }
}

通过代码生成创建适配器

对于具有大量模型的项目,Hive 提供 hive_generatorbuild_runner。类上的 @HiveType 注解和字段上的 @HiveField 注解会自动生成适配器。当模型包含 10 个以上字段时,这很方便 — 手动编写 read/write 变得繁琐。

优化 Hive 性能

Hive 从内存而非磁盘执行读取,提供每秒高达 30,000 次操作的速度。优化建议:一次打开 Box 并在整个应用中重复使用,不要再次调用 openBox。初始化后使用 Hive.box()(同步 getter)— 返回已打开的 Box 而无需创建新实例。

Hive 与 Provider 和 Riverpod 结合

Hive 可轻松与流行的 Flutter 状态管理器集成。对于 Provider,使用在初始化时从 Box 读取数据并通过 listenable 更新的 ChangeNotifierProvider。对于 Riverpod,适合订阅 WatchBox 的 StreamProvider。这种组合在每次 Hive 中数据变更时提供响应式 UI 更新,无需手动调用 setState。在典型的 Flutter 项目中,这种架构允许在屏幕之间同步状态而无需全局 singleton。

常见问题

可以在没有 Flutter 的情况下使用 Hive 吗?

Hive 在纯 Dart 中运行,因此可在任何 Dart 项目中使用:服务器端(Dart VM)、控制台或 AngularDart。对于 Flutter,额外连接带有存储路径初始化的 hive_flutter

如何在 Hive 中加密数据?

Hive 在打开 Box 时通过 encryptionKey 参数支持 AES-256 加密。密钥必须是 32 字节的字符串。加密后的 Box 在没有密钥的情况下无法读取 — 数据在文件级别受到保护。

Hive 与 Isar 有何不同?

Isar — 来自同一作者(Simon Leiter)的 Hive 继承者。Isar 更快,支持索引、关联和复杂查询。然而,对于不需要 Isar 关系型功能的简单场景以及对于最小依赖很重要的项目,Hive 仍然适用。

Hive 支持模式迁移吗?

Hive 没有内置的迁移功能。如果 TypeAdapter 结构发生变化,旧数据将无法反序列化。解决方法:增加适配器的 typeId 并在代码中编写手动迁移,或者在写入新键之前对旧键使用 delete

Hive Box 的最大大小是多少?

Hive 将 Box 完全加载到内存中。建议限制为每个 Box 50-100 MB。超过时,可能会出现 Box 打开延迟和 RAM 消耗增加。对于更大的数据量,请使用多个 Box 或带延迟加载的 LazyBox。

总结

  • Hive — 纯 Dart 的 NoSQL 数据库,无需原生代码和平台依赖
  • 速度 — 在移动设备上每秒高达 30,000 次读取操作
  • TypeAdapter — 自定义对象的二进制序列化,无需反射
  • WatchBox — 自动 UI 更新的响应式变更跟踪
  • 跨平台 — Android、iOS、Web、macOS、Windows、Linux 开箱即用
  • 加密 — Box 文件级别的 AES-256 数据保护
  • 建议 — 在 Flutter 和 Dart 项目中,将 Hive 用于缓存、设置和小数据量

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读