Hive 是一个在移动应用和桌面应用中实现高性能、轻量级本地数据存储的解决方案。它将数据存储在应用的文件系统中,通常是应用的沙盒目录(sandbox directory)。
具体来说,Hive 将数据存储在应用的文件系统中的特定目录中。在 Flutter 中,Hive 默认将数据存储在应用的沙盒目录下的一个名为 hive 的子目录中。
这个目录中包含了各种用于存储数据的文件,包括:
*.hive 文件:这些是实际的 Hive 数据库文件,其中存储了通过 Hive 存储的数据。不同的 Hive Box(类似于数据库表)会有不同的文件。
*.lock 文件:这些是用于在多个操作之间进行同步的锁文件。它们确保在进行读取和写入操作时,数据不会出现冲突。
*.log 文件:这些文件用于记录 Hive 操作的日志,以便在需要时进行故障排除。
Hive 以一种非常轻量级的方式将数据存储在文件系统中,这使得数据读取和写入的性能非常高效。同时,Hive 还支持将数据序列化为不同的格式,例如二进制、JSON 等,以提高存储和读取效率。
总结起来,Hive 将数据存储在应用的文件系统中,使得您的应用能够高效地在本地进行数据存储和检索。
添加依赖
dependencies:
hive: ^[version]
hive_flutter: ^[version]
dev_dependencies:
hive_generator: ^[version]
build_runner: ^[version]
数据存储在box里面,没有固定的结构,可以存储任何数据
对于小的项目,一个 box 就够用了,但是对于大的项目,需要多个
在使用 Box 之前必须要将其打开
var box = await Hive.openBox('testBox');
Why use Hive
Hive 是一个在移动应用和桌面应用中实现高性能、轻量级本地数据存储的解决方案。它将数据存储在应用的文件系统中,通常是应用的沙盒目录(sandbox directory)。
具体来说,Hive 将数据存储在应用的文件系统中的特定目录中。在 Flutter 中,Hive 默认将数据存储在应用的沙盒目录下的一个名为 hive 的子目录中。
这个目录中包含了各种用于存储数据的文件,包括:
*.hive 文件:这些是实际的 Hive 数据库文件,其中存储了通过 Hive 存储的数据。不同的 Hive Box(类似于数据库表)会有不同的文件。
*.lock 文件:这些是用于在多个操作之间进行同步的锁文件。它们确保在进行读取和写入操作时,数据不会出现冲突。
*.log 文件:这些文件用于记录 Hive 操作的日志,以便在需要时进行故障排除。
Hive 以一种非常轻量级的方式将数据存储在文件系统中,这使得数据读取和写入的性能非常高效。同时,Hive 还支持将数据序列化为不同的格式,例如二进制、JSON 等,以提高存储和读取效率。
总结起来,Hive 将数据存储在应用的文件系统中,使得您的应用能够高效地在本地进行数据存储和检索。
添加依赖
dependencies:
hive: ^[version]
hive_flutter: ^[version]
dev_dependencies:
hive_generator: ^[version]
build_runner: ^[version]
数据被存储在盒子内部,没有固定的结构,可以存储任何类型的数据。
对于小型项目,一个盒子足够,但对于大型项目,需要多个盒子。
使用 Box之前必须打开
var box = await Hive.openBox('testBox');
如果这个盒子之前已经打开了可以使用,如果没有打开不可以用
var box = Hive.box('myBox');
使用完后要记得关闭,所有活动的读写操作完成后,盒子的所有缓存键和值将从内存中删除,并且盒子文件将关闭。
var box = await Hive.openBox('myBox');
await box.put('hello', 'world');
await box.close();
打开一个指定类型的 Box ,但是不可以同时用不同的类型打开同一个 Box
var box = await Hive.openBox('users');
box.add(User());
box.add(5); // 编译时错误
await Hive.openBox('users');
Hive.box('users'); // OK
Hive.box('users'); // ERROR
Hive.box('users'); // ERROR
从 box 里面读取数据是很直接的操作,你提供所需要数据的 key ,就可以返回 对应的value000
var box = Hive.box('myBox');
String name = box.get('name');
DateTime birthday = box.get('birthday');
注意,如果你提供的 key 对应的value不存在的话,会返回 null,为了避免这种情况的发生,我们可以设置一个返回值
double height = box.get('randomKey', defaultValue: 17.5);
在使用 get() 方法获取数据时,返回的列表类型是 List(键值对为 Map
)。如果您希望将它们转换为特定类型,您需要使用 list.cast() 来进行类型转换。
将数据写入盒子几乎就像写入映射一样。所有键都必须是ASCII字符串,最大长度为255个字符,或者是无符号32位整数。
var box = Hive.box('myBox');
box.put('name', 'Paul');
box.put('friends', ['Dave', 'Simon', 'Lisa']);
box.put(123, 'test');
box.putAll({'key1': 'value1', 42: 'life'});
您可能想知道为什么在没有异步代码的情况下可以进行编写。这是 Hive 的主要优势之一。
更改会在后台尽快写入磁盘,但所有侦听器都会立即收到通知。如果异步操作失败(不应该失败),所有侦听器都会再次收到旧值的通知。
如果您想确保写入操作成功,只需等待其Future.
var box = await Hive.openBox('box');
box.put('key', 'value');
print(box.get('key')); // value
var lazyBox = await Hive.openLazyBox('lazyBox');
var future = lazyBox.put('key', 'value');
print(lazyBox.get('key')); // null
await future;
print(lazyBox.get('key')); // value
可以选择用null覆盖或者直接删除
box.put("age","10");
print(box.get("age"));
box.put("age", null);
print(box.get("age",defaultValue: "33"));
box.delete("age");
print(box.get("age",defaultValue: "33"));
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
void main() async {
await Hive.initFlutter();
await Hive.openBox('settings');
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo Settings',
home: Scaffold(
body: ValueListenableBuilder(
valueListenable: Hive.box('settings').listenable(),
builder: (context, box, widget) {
return Center(
child: Switch(
value: box.get('darkMode', defaultValue: false),
onChanged: (val) {
box.put('darkMode', val);
},
),
);
},
),
),
);
}
}
怎么理解上面的代码
MyApp 类是一个无状态的小部件,构建了一个带有开关(Switch)的用户界面,用于切换夜间模式。以下是代码的详细解释:
MaterialApp 是 Flutter 应用的顶层小部件,定义了应用的一些元信息。
Scaffold 是一个用于构建典型应用页面布局的小部件。
ValueListenableBuilder 是一个构建小部件的帮助工具,它可以根据 Hive 盒子中的变化来重新构建 UI。
在 ValueListenableBuilder 内部,您监听了 Hive 盒子 ‘settings’ 的变化,每当盒子中的数据发生变化时,UI 就会重新构建。
Switch 是一个切换按钮,用于在开启和关闭之间进行切换。
value 参数是用于设置 Switch 是否选中的值,这里是从 Hive 盒子中获取 ‘darkMode’ 键对应的值,默认值是 false。
onChanged 参数是一个回调函数,当用户切换开关时,将会调用这个函数。在这个函数中,您使用 box.put 将新的开关状态存储到 Hive 盒子中。
这个示例应用展示了如何使用 Hive 存储和读取设置数据,并通过 UI 反映设置的变化。这是一个简单的示例,您可以根据自己的需求扩展和修改。
我们再次单独理解一下
当用户点击开关(Switch)时,onChanged 回调会被触发。这个回调接收一个参数 val,表示开关的新状态,即用户是否切换了开关的选中状态。
如果开关被打开,val 的值为 true;如果开关被关闭,val 的值为 false。这是因为开关表示一个布尔值的状态,选中代表 true,未选中代表 false。
所以,当您点击开关时,onChanged 回调会根据用户的操作将 true 或 false 传递给 val,然后您使用 box.put(‘darkMode’, val) 将这个值存储到 Hive 盒子中,以便在以后可以读取它并根据用户的设置来调整应用的行为。
如果您希望您的小部件根据存储在Hive中的数据进行刷新,您可以使用ValueListenableBuilder。box.listenable() 方法提供了一个ValueListenable,它还可以与provider包一起使用。
如果只想监听特定 key ,可以用下面的代码
ValueListenableBuilder(
valueListenable: Hive.box('settings').listenable(keys: ['firstKey', 'secondKey']),
builder: (context, box, widget) {
// build widget
},
)
自动增量和索引
我们已经知道 Hive 支持无符号整数键。如果您愿意,可以使用自动递增键。这对于存储和访问多个对象非常有用。您可以像列表一样使用 Box。
还有getAt()、putAt()和deleteAt()方法可以通过索引访问或更改值。
import 'package:hive/hive.dart';
void main() async {
var friends = await Hive.openBox('friends');
friends.clear();
friends.add('Lisa'); // index 0, key 0
friends.add('Dave'); // index 1, key 1
friends.put(123, 'Marco'); // index 2, key 123
friends.add('Paul'); // index 3, key 124
print(friends.getAt(0));
print(friends.get(0));
print(friends.getAt(1));
print(friends.get(1));
print(friends.getAt(2));
print(friends.get(123));
print(friends.getAt(3));
print(friends.get(124));
}