[基礎知識]HiveによるDB操作

FlutterでDB機能を実装する手法として、Hiveパッケージがあります。
Hiveでは、NoSQLデータベース(高速かつキー・バリュー型のデータベース。シリアライズ不要で、シンプルなデータ保存が可能。)を扱います。
故に、Hiveのメリット・デメリット等の特徴も、それに準じた内容で、以下の様になります。

Hiveパッケージの特徴:

メリット:

(1) 高速

  • 説明: Hiveは特に高速なパフォーマンスを誇ります。内部的にバイナリフォーマットを使用してデータを保存するため、データの読み書きが非常に速いです。
  • 利点: 大量のデータを頻繁に読み書きするアプリケーションに適しています。

(2) 軽量

  • 説明: Hiveは軽量なデータベースで、依存関係が少ないです。パッケージ自体が小さいため、アプリのビルドサイズにほとんど影響を与えません。
  • 利点: パフォーマンスに敏感なモバイルアプリケーションに適しています。

(3) 型安全

  • 説明: HiveはDartの型システムと完全に統合されています。TypeAdapterを使用することで、データのシリアライズとデシリアライズが型安全に行えます。
  • 利点: コンパイル時に型チェックが行われるため、ランタイムエラーを減らすことができます。

(4) シンプルなAPI

  • 説明: HiveのAPIはシンプルで直感的です。データベース操作のための学習曲線が緩やかです。
  • 利点: 初心者でも簡単に学習し、使用することができます。

(5) オフライン対応

  • 説明: Hiveは完全にオフラインで動作します。インターネット接続がなくてもデータの読み書きが可能です。
  • 利点: オフラインファーストのアプリケーションに適しています。

(6) クロスプラットフォーム

  • 説明: HiveはFlutterを使用するすべてのプラットフォーム(Android、iOS、Web、デスクトップ)で動作します。
  • 利点: マルチプラットフォーム対応のアプリケーションを簡単に構築できます。

上記の様に、軽快・安全・シンプルといったメリットがある一方、以下の様なデメリットもあるようです。

デメリット:

(1) リレーショナルデータベースのサポート不足

  • 説明: Hiveはキー・バリュー型のデータベースであり、リレーショナルデータベースのような複雑なクエリや結合操作をサポートしていません。
  • 欠点: リレーションが必要なデータ構造や複雑なクエリを必要とするアプリケーションには不向きです。

(2) 型の制約

  • 説明: HiveのTypeAdapterを使用するためには、モデルクラスに特定のアノテーションを付ける必要があり、TypeAdapterの生成も必要です。
  • 欠点: データモデルの変更があるたびにTypeAdapterの再生成が必要となり、少し手間がかかることがあります。

(3) ウェブサポートの制限

  • 説明: HiveはWebプラットフォームもサポートしていますが、Webブラウザの制限によりパフォーマンスが低下する場合があります。
  • 欠点: 大量のデータを扱うWebアプリケーションにはパフォーマンスの問題が発生する可能性があります。

(4) ドキュメントの制約

  • 説明: SQLiteなどの他のデータベースソリューションと比べると、Hiveのドキュメントやコミュニティサポートが少ない場合があります。
  • 欠点: 問題が発生した場合、解決方法を見つけるのに時間がかかることがあります。

上記の様に、いわばRDBMSとNoSQLデータベースの、両者の特徴が、そのままHiveパッケージの特徴、となっています。

このように、Hiveは、多くのユースケースにおいて非常に強力なツールですが、プロジェクトの特定のニーズに応じて他のデータベースソリューションと比較し、適切な選択をすることが重要です。例えば、複雑なリレーショナルデータを扱う必要がある場合や、Webプラットフォームで高いパフォーマンスが求められる場合は、他のソリューションを検討することも考慮してください。

以下、Hiveの利用手順です。

Hiveの利用手順:

1.Flutterプロジェクト作成

(1) ターミナルを開き、以下のコマンドを実行して新しいプロジェクトを作成します。

flutter create hive_example

(2) プロジェクトフォルダに移動します。

cd hive_example

2.必要なパッケージの追加

Hiveを使用するために必要なパッケージ(次の4つ)を追加します。

hive と hive_flutter は、アプリ実行時に使用されます。
故に、pubspec.yaml では、dependencies 句に登録します。

しかし、build_runner と hive_generator は、開発段階で使用します。
故に、pubspec.yaml では、dev_dependencies 句に登録します。

https://pub.dev/packages/hive/install
https://pub.dev/packages/hive_flutter/install
https://pub.dev/packages/build_runner/install
https://pub.dev/packages/hive_generator/install

2.1 アプリ実行時に必要な(hive、hive_flutter)パッケージの追加

(1) プロジェクトフォルダで次のコマンドによりhiveパッケージとhive_flutterパッケージ(の依存関係)を追加します。

flutter pub add hive
flutter pub add hive_flutter

(2) pubspec.yaml ファイルを開き、上記パッケージ(の依存関係)が追加されていることを確認します。

dependencies:
  flutter:
    sdk: flutter

  hive: ^2.2.3
  hive_flutter: ^1.1.0

(3) ターミナルで以下のコマンドを実行してパッケージをインストール(反映)します。

flutter pub get

2.2 開発時に必要な(build_runner、hive_generator)パッケージの追加

(1) pubspec.yaml ファイルを開き、上記パッケージ(の依存関係)を追加します。

dev_dependencies:
  flutter_test:
    sdk: flutter

  build_runner: ^2.4.11
  hive_generator: ^2.0.1

(2) ターミナルで以下のコマンドを実行してパッケージをインストール(反映)します。

flutter pub get

3.Hiveデータベースの設定と使用

以下は、Hiveデータベースを設定(モデルクラス作成)し、使用するためのサンプルコードです。

3.1 モデルクラス作成

まず、Hiveに保存するデータのモデルクラスを作成します。

(1) lib フォルダ内に item.dart ファイルを作成します。

(2) item.dartの内容:

import 'package:hive/hive.dart';

part 'item.g.dart';

// Hiveオブジェクトとして登録
@HiveType(typeId: 0)
class Item extends HiveObject {
  @HiveField(0)
  String name;

  Item({required this.name});
}

3.2 TypeAdapter生成

次に、Hiveのコード生成機能を使用してTypeAdapterを生成します。

(1) ターミナルで以下のコマンドを実行してTypeAdapterを生成します。

flutter pub run build_runner build

3.3 サンプルアプリの作成

次に、サンプルアプリを作成してHiveデータベースを利用します。

(1) lib/main.dart ファイルを開き、以下のコードを追加します。

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';

import 'item.dart';

void main() async {
  // Hiveを初期化
  await Hive.initFlutter();

  // TypeAdapterを登録
  Hive.registerAdapter(ItemAdapter());

  // ボックスを開く
  await Hive.openBox<Item>('items');

  runApp(const MyApp());
}

// メインアプリケーションクラス
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Hive Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

// ホーム画面クラス
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  MyHomePageState createState() => MyHomePageState();
}

// ホーム画面の状態を管理するクラス
class MyHomePageState extends State<MyHomePage> {
  final TextEditingController _controller = TextEditingController(); // テキストフィールドのコントローラ
  late Box<Item> _itemBox; // Hiveのボックスを参照する変数

  @override
  void initState() {
    super.initState();
    _itemBox = Hive.box<Item>('items'); // ボックスを取得
  }

  // アイテムを追加するメソッド
  Future<void> _addItem(String name) async {
    final newItem = Item(name: name); // 新しいアイテムを作成
    await _itemBox.add(newItem); // アイテムをボックスに追加
    _controller.clear(); // テキストフィールドをクリア
    setState(() {}); // 状態を更新してリストをリフレッシュ
  }

  // アイテムを削除するメソッド
  Future<void> _deleteItem(int index) async {
    await _itemBox.deleteAt(index); // 指定したインデックスのアイテムを削除
    setState(() {}); // 状態を更新してリストをリフレッシュ
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Hive Example'),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              controller: _controller,
              decoration: InputDecoration(
                labelText: 'Item Name',
                suffixIcon: IconButton(
                  icon: const Icon(Icons.add),
                  onPressed: () {
                    if (_controller.text.isNotEmpty) {
                      _addItem(_controller.text); // アイテムを追加
                    }
                  },
                ),
              ),
            ),
          ),
          Expanded(
            child: ValueListenableBuilder(
              valueListenable: _itemBox.listenable(),
              builder: (context, Box<Item> box, _) {
                if (box.values.isEmpty) {
                  return const Center(child: Text('No items')); // アイテムがない場合の表示
                }
                return ListView.builder(
                  itemCount: box.length,
                  itemBuilder: (context, index) {
                    final item = box.getAt(index);
                    return ListTile(
                      title: Text(item!.name), // アイテムの名前を表示
                      trailing: IconButton(
                        icon: const Icon(Icons.delete),
                        onPressed: () {
                          _deleteItem(index); // アイテムを削除
                        },
                      ),
                    );
                  },
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

3.4 動作確認

下の様に、Item Name(TextField)に入力し、+アイコン(IconButton)をクリックすると、その都度、入力データがSQLiteに登録され、その下の表示欄(ListTile)に表示されていきます。

4.まとめ

Hiveの利用手順は、
①パッケージ追加(アプリ実行時に必要な2つ(hive、hive_flutter))
②パッケージ追加(開発時に必要な2つ(build_runner、hive_generator))
③Hiveで使用するデータのモデルクラス作成(例:item.dart)
④コード生成機能によるTypeAdapter生成(例:item.g.dart)
⑤サンプルコード作成(例:main.dart)
という順番で行います。

上記②~④を注意すれば、極めて容易に、DB操作を実現できます。

コメントを残す