---
title: 'Flutter Database(Hive)'
tags: Flutter
disqus: hackmd
---
<style>
.red {
color: red;
}
.blue {
color: blue;
}
</style>
<font size="6">Flutter Database(Hive)</font>
**目錄:**
[TOC]
---
Flutter提供了許多本地數據持久化選項供開發者選擇。shared_preferences是一個用於本地存儲小型鍵值對的好包,而sqflite,Flutter的SQLite包,當你處理強關係型數據,需要你在數據庫中處理複雜的關係時,是一個不錯的選擇。
但是如果你想要一個快速安全的本地數據庫,沒有本地的依賴性,也能在Flutter web上運行,那麼Hive是一個相當不錯的選擇。
在這篇文章中,在我們使用Flutter構建一個簡單的應用程序之前,你將學習如何開始使用Hive。我們還將研究一個允許你在Hive中處理簡單關係數據的概念。
## 為什麼是Hive?
Hive是一個輕量級和快速的鍵值數據庫解決方案,它是跨平台的(在移動、桌面和網絡上運行),並且是用純Dart編寫的。這使得它比<span class='red'>不支持Flutter網絡的sqflite</span>更有優勢--Hive沒有原生的依賴性,所以它可以在網絡上無縫運行。
順帶一題Hive是使用<span class='blue'>NoSQL</span>數據庫
下面是一張Hive與其他類似數據庫解決方案的基準圖。

這是一個在安卓Q系統的Oneplus 6T設備上進行的1000次讀寫操作的基準
## 開始使用Hive
```shell=
flutter pub add hive
flutter pub add hive_flutter
```
## 了解盒子
Hive使用"盒子"的概念來存儲數據庫中的數據。盒子類似於SQL數據庫中的表,只是盒子缺乏嚴格的結構。這意味著盒子很靈活,只能處理數據之間的簡單關係。
在本教程中,我們將只介紹典型的Hive盒子,但值得一提的是,你也可以創建[懶惰的盒子](https://docs.hivedb.dev/#/advanced/lazy_box)和[加密的盒子](https://docs.hivedb.dev/#/advanced/encrypted_box)。
## 初始化Hive
在進入數據庫的CRUD操作之前,你必須初始化Hive並打開一個用於存儲數據的盒子。
Hive應該在我們加載任何盒子之前被初始化,所以最好在你的Flutter應用程序的main()函數中初始化它,以避免任何錯誤。
:::warning
如果你在一個非Flutter的純Dart應用程序中使用Hive,你應該使用Hive.init()來初始化Hive。
:::
```dart=
void main() async {
// Required for async calls in `main`
WidgetsFlutterBinding.ensureInitialized();
// Initialize hive
await Hive.initFlutter();
runApp(const MyApp());
}
```
使主函數異步化,並使用await來初始化Hive。
現在,你必須要打開一個Hive盒子。
:::warning
如果你打算在你的項目中使用盒子,你應該在使用一個盒子之前打開它。
:::
在這個應用程序中,我們將使用一個盒子,在Hive完成初始化後再打開。
```dart=
void main() async {
// Required for async calls in `main`
WidgetsFlutterBinding.ensureInitialized();
// Initialize hive
await Hive.initFlutter();
// Open the peopleBox
await Hive.openBox('peopleBox');
runApp(const MyApp());
}
```
## 執行CRUD操作
```dart=
class InfoScreen extends StatefulWidget {
@override
_InfoScreenState createState() => _InfoScreenState();
}
class _InfoScreenState extends State<InfoScreen> {
late final Box box;
@override
void initState() {
super.initState();
// Get reference to an already opened box
box = Hive.box('peopleBox');
}
@override
void dispose() {
// Closes all Hive boxes
Hive.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
```
首先,我們在initState()方法裡面檢索一個對我們先前打開的盒子的引用。你應該在使用完之後,在關閉應用程序之前總是關閉已打開的盒子。
由於我們目前只需要這個部件裡面的盒子,我們可以在這個類的dispose()方法裡面關閉這個盒子。
創建方法來執行CRUD操作。
### 存儲數據
如果你需要存儲數據,你可以使用對Hive盒子的引用並對其調用put()。
這個方法接受一個鍵值對。
```dart=
// Add info to people box
_addInfo() async {
// Storing key-value pair
box.put('name', 'John');
box.put('country', 'Italy');
print('Info added to box!');
}
```
Hive也支持整數鍵,所以你可以使用自動遞增的鍵。
如果你要存儲多個值(有點類似於列表),並想通過它們的索引進行檢索,你可以像這樣存儲。
```dart=
box.add('Linda'); // index 0, key 0
box.add('Dan'); // index 1, key 1
```
### 檢索數據
要讀取數據,你可以使用盒子對像上的get()方法。
你只需要提供key來檢索它的值。
```dart=
// Read info from people box
_getInfo() {
var name = box.get('name');
var country = box.get('country');
print('Info retrieved from box: $name ($country)');
}
```
如果你使用的是自動遞增的值,你可以使用索引來讀取。
```dart=
box.getAt(0); // retrieves the value with index 0
box.getAt(1); // retrieves the value with index 1
```
### 更新數據
要更新一個特定鍵的數據,你可以使用你最初用來存儲值的相同的put()方法。
這將用新提供的值更新存在於該鍵的值。
```dart=
// Update info of people box
_updateInfo() {
box.put('name', 'Mike');
box.put('country', 'United States');
print('Info updated in box!');
}
```
如果你使用的是自動遞增的值,你可以使用putAt()方法來更新存在於特定索引的值。
```dart=
box.putAt(0, 'Jenifer');
```
### 刪除數據
對於刪除數據,你可以通過提供鍵來使用delete()方法。
這將刪除存在於這些特定鍵的值。
如果你試圖使用這些鍵調用get()方法,它將返回空值。
```dart=
// Delete info from people box
_deleteInfo() {
box.delete('name');
box.delete('country');
print('Info deleted from box!');
}
```
如果你使用的是自動遞增的值,你可以通過提供索引來使用deleteAt()方法。
```dart=
box.deleteAt(0);
```
## 使用TypeAdapter的自定義對象
:::danger
未完成
:::
## 查看
點擊F12查看

檔案位置
```shell=
~/Library/Application\ Support/Google/Chrome/Default
```