【Flutter】Hiveの使い方
Hiveは端末のローカル保存領域をデータベースとして使用するためのパッケージです。Hiveを使用することで簡単かつ高速にデータの保存/取得を行うことができます。
パッケージのインストール
Hiveを使用するためにpubspec.yaml のdependencies に以下のコードを記述します。
そしてflutter pub get コマンドを実行することでHiveを使用することができるようになります。
Hiveの基本的な使い方
Hiveを初期化する
Hiveでデータを保存/取得する前にHive クラスのinitFlutter() を実行して、Hive クラスを初期化します。
Box型の変数を宣言する
Box クラスはデータを保存/取得するためのメソッドが集まっているクラスです。HiveではBox インスタンスを介してデータの保存/取得を行います。
Boxインスタンスを取得する
Hive クラスが持つopenBox() の引数にキーを指定することで、キーに対応するBox インスタンスを取得することができます。以下のサンプルコードではbox1 をキーとし、対応するBox インスタンスを取得してbox 変数に代入しています。
データを保存する
Box インスタンスが持つput() の引数にキーと保存したいデータを指定することで、キーとデータをペアにして保存することができます。以下のサンプルコードでは'count' をキーとして、int 型の値を保存しています。
データを取得する
Box インスタンスが持つget() の引数にキーを指定することで、キーに対応するデータを取得することができます。以下のサンプルコードでは前項で保存した'count' キーに対応するデータを取得しています。引数のdefaultValue にデータを指定することで、'count' キーに対応するデータが存在しない時に代わりに渡すデータを指定することができます。
全体コード

上記はフローティングボタンをタップする度に、画面中央に表示している数値がカウントアップするアプリのコードです。フローティングボタンをタップすることで_counter がインクリメントされ、画面中央に表示される数値がカウントアップされます。そしてフローティングボタンをタップする度に以下のコードが実行されます。
これはインクリメントした数値を'count' をキーとして端末のローカル保存領域に保存するコードになります。
_MyHomePageState がリビルドされる際、以下のコードが実行されます。
これは端末のローカル保存領域に保存されている'count' キーに対応するデータを取り出すコードになります。'count' キーに対応するデータが存在していない時は_counter に0 が代入されます。つまり、初回起動時は'count' キーに対応するデータは存在していないので_counter に0 が代入されます。
数回フローティングボタンをタップした後アプリを終了し、再度アプリを起動すると、_counter には前回端末のローカル保存領域に保存した'count' キーに対応するデータが代入されます。
その結果、画面には前回表示していた数値が表示されるようになります。

ここまでがHiveの基本的な使い方です。以降ではBox クラスに用意されているデータの取り扱いに関するメソッドや、オリジナルクラスの保存/取得といったもう少し踏み込んだ使い方を説明していきます。
Boxクラスのメソッド
事前準備
_MyHomePageState クラスに以下のメソッドを追加します。
上記を実行すると'count0' - 'count4' をキーとして0 - 4 の数値が端末のローカル保存領域に保存されます。実際にBox インスタンスを介して端末のローカル保存領域を確認してみます。
box.keys 、box.values でBox インスタンスを介して端末のローカル保存領域に保存された全てのキー、値をリストで取得することができます。これらをコンソールに出力すると、

が表示されることから保存した順番にキーと数値が端末のローカル保存領域に保存されていることがわかります。
データを保存
.put(key, data) でkey に対応するdata を保存することができます。上記のサンプルコードでは'count' をキーとして1 を保存しています。
インデックス番号を指定してデータを保存
.putAt(index, data) でindex で指定したインデックス番号のキーに対してdata を保存することができます。事前準備で記載したサンプルコードを実行した後に上記サンプルコードを実行すると、インデックス番号が0 に対応するキーは'count0' となるので、'count0' をキーとして99 を保存しています。

データを取得
.get(key, defaultValue: defaultData) でkey に対応するデータを取得することができます。defaultValue はオプション引数です。key に対応すデータがローカル保存領域に存在しない時はdefaultData を取得します。
上記のサンプルコードでは'count' キーに対応するデータを取得しています。もし、'count' キーに対応するデータが存在していない時は0 を取得します。
インデックス番号を指定してデータを取得
.getAt(index) のindex で指定したインデックス番号のキーに対応するデータを取得することができます。
事前準備で記載したサンプルコードを実行した後に上記サンプルコードを実行すると、インデックス番号が0 に対応するキーは'count0' となるので、'count0' キーに対応するデータを取得することができます。
データを削除
.delete('key', data) でkey とkey に対応するdata をローカル保存領域から削除することができます。
事前準備で記載したサンプルコードを実行した後に上記サンプルコードを実行すると、キーである'count0' と、'count0' キーに対応するデータを削除することができます。

インデックス番号を指定してデータを削除
.deleteAt(index) のindex で指定したインデックス番号のキーと、そのキーに対応するデータをローカル保存領域から削除することができます。
例えば、事前準備で記載したサンプルコードを実行した後に上記サンプルコードを実行すると、1番目のインデックス番号の'count1'キーと'count1'キーに対応するデータを削除することができます。

複数のデータを一括削除
.deleteAll([key, key,...]) で引数のkey のリストに対応するデータ群をローカル保存領域から削除することができます。
例えば、事前準備で記載したサンプルコードを実行した後に上記サンプルコードを実行すると、'count1' 、'count2' キーとそれらのキーに対応するデータを削除することができます。

データを全て削除
.deleteFromDisk() で.deleteFromDisk()をコールしたBox インスタンスを介して保存した全てのキーとデータを削除することができます。
オリジナルクラスの保存/取得
パッケージの追加インストール
後述するオリジナルクラスのタイプアダプタークラスを作成するために、hive_generator 、build_runner パッケージを追加でインストールします。
そしてflutter pub get コマンドを実行してください。
タイプアダプタークラスの作成
タイプアダプターとはクラスのインスタンスをバイナリ形式のインスタンスに変換したり、バイナリ形式のインスタンスからオリジナルクラスのインスタンスに変換する機能を指します。Hiveを使用してオリジナルクラスの保存/取得を行うには、オリジナルクラスのタイプアダプタークラスを作成する必要があります。
タイプアダプタークラスを作成する方法は
- 自身の手でコードを書く
-
hive_generatorを使用して自動で生成する
の2パターンがあります。
今回はhive_generator を使用して自動でタイプアダプタークラスを生成する方法を説明します。
例えば、以下のようなユーザ情報をプロパティに持つUser クラスをuser.dart に定義します。
Hiveを使用してこのUser クラスのインスタンスの保存/取得を行うには、User クラスのタイプアダプタークラスを作成する必要があります。
User クラスのタイプアダプタークラスを自動生成するため、User クラスを以下のように修正します。
part はpart of と組み合わせて使用するものでプログラムを分割する際に使用します。つまり今回の例だと、user.dart とuser.g.dart は一つのファイルで定義したことと同等の状態になります。
user.g.dart はタイプアダプタークラスを定義するファイルになります。現段階ではuser.g.dart は生成していないのでビルドを実行してもビルドエラーが発生します。
またuser.g.dart はuser.dart と同じディレクトリに生成されるため、以下のようなディレクトリ構成に変更しておきましょう。

@HiveType(typeId: )
タイプアダプタークラスを作成するモデルクラスには@HiveType(typeId: ) を指定します。上記のサンプルソースだとUserクラス宣言直前に@HiveField(typeId: ) を記載します。
@HiveField
タイプアダプタークラスを作成するモデルクラスのフィールドには@HiveField() を指定します。上記のサンプルソースだとname 、 age変数宣言直前にそれぞれ@HiveField() を記載します
タイプアダプタークラスの自動生成
ターミナルを立ち上げ、タイプアダプタークラスを作成するプロジェクト直下に移動します。そして
以下のコマンドを実行してください。
flutter packages pub run build_runner build
するとターミナルに次々と進行状況が表示されます。

ターミナルに[INFO] Succeeded after ** s with ** outputs (** actions)が表示されると、タイプアダプタークラスを定義したuser.g.dart がtypeadapter ディレクトリ直下に生成されます。

タイプアダプタークラスの登録
Hiveを使用してこのオリジナルクラスのインスタンスの保存/取得を行うには、オリジナルクラスに対応するタイプアダプタークラスのインスタンスをHive クラスに登録する必要があります。
上記のサンプルソースではHive クラスのregisterAdapter() にUser クラスに対応するアダプタークラスのUserAdapter インスタンスを指定することで、Hiveを使用してUser クラスの保存/取得を行うことができるようになっています。
全体ソースコード
上記は画面中央に名前と年齢を表示し、テキストフィールドで名前と年齢を変更することがでできるアプリのコードです。アプリ初回起動時は、名前はAnninymus 、年齢は 0 となっています。

テキストフィールド経由で名前と年齢を変更して、アプリを終了してみます。
そしてアプリを再起動すると、アプリを終了させる前の名前と年齢が表示させることができています。

このことから、Hiveを使用してUser クラスの保存/取得を行うことができるようになってることを確認することができます。
参考文献
Discussion