Studyplus Engineering Blog

スタディプラスの開発者が発信するブログ

FlutterのローカルDB対応

こんにちは、モバイルクライアントグループの隅山です。 Flutter開発がメインになってしばらく経ちますが、今回はローカルDB対応でIsarを導入した話をします。

pub.dev

FlutterのローカルDBパッケージはたくさんあって悩みますが、下記の理由でIsarを選びました。

  • Hiveの後継として機能が豊富
  • マルチプラットフォーム対応されている
  • Isar Inspectorで保存されているデータを見られる

Isarは非常に使いやすいため、今回は具体的な使い方を紹介します。

Isar

元々NoSQLのDatabaseとしてHiveというパッケージがありました。

pub.dev

Hiveがリリース後に改善されていくなか、Hiveの作者は大きく作り変える必要があると考え、v2として別パッケージでIsarが作成されました。 Hiveの後継としてIsarがリリースされたため、機能が豊富に搭載されています。 そして、マルチプラットフォーム対応としてiOS, Android, Desktop, Webにも対応されているのも大きなメリットの1つです。

Isar Inspector

Isar InspectorはアプリのIsarインスタンスや保存されているデータをリアルタイムにみることができます。

github.com

この機能が非常に便利であり、開発中にいつ何のデータが保存されたかや削除されたかをリアルタイムで確認できます。 保存されたデータのプロパティまで見ることができ、さらにプロパティの書き換えも簡単に行うことができます。 プロパティによってUIを出し分けている場合は、プロパティの書き換えによって検証も非常に楽になります。

Isarの導入方法はIsarのページで紹介されているので、次に具体的な使い方を紹介していきます。

isar.dev

具体的な使い方

Isarでは保存したいデータをコレクションとして扱うことになります。 コレクションとして定義するにはClassにアノテーションをつけます。

@collection
class User {
  Id? id;

  String? firstName;

  String? lastName;
}

コレクションを識別するIdプロパティを定義する必要があります。 Idは自分で設定できますが、nullを指定してオートインクリメントで自動割り当てにもできます。

コレクションの読み書きをする場合、単一データを扱うか複数データを扱うかで取得方法が異なるので次にそれぞれの方法を紹介します。

単一データの読み書き

単一データの読み書きは以下のようになります。

final Isar isar;

Future<User?> find() async =>
  await isar.users.where().findFirst();

Future<void> put(User user) async {
  await isar.writeTxn(() async {
    await isar.clear();
    await isar.users.put(user);
  });
}

Future<void> clear() async {
  await isar.writeTxn(() async {
    await isar.users.clear();
  });
}

単一データか複数データかをわかりやすくするため、直接Isarで読み書きせずにメソッドを用意しました。 通常コレクションのデータを取得する場合はgetでIdを指定するかfindAllで全データを取得するかですが、単一データを扱う場合はfindFirstですみます。 そして保存はclearの後にputすることで毎回更新するようにしています。

このようにメソッドを用意することで非常に使いやすくなります。 そして下記の画像が上のコードを動かした場合のIsar Inspectorとなります。 Isar Inspectorでデータが保存されていることをリアルタイムで確認できます。

データ追加前後のIsar Inspector

複数データの読み書き

複数データの読み書きは以下のようになります。

final Isar isar;

Future<List<User>> findAll() async =>
    await isar.users.where().findAll();

Future<void> addAll(List<User> users) async {
  await isar.writeTxn(() async {
    await isar.users.putAll(users);
  });
}

Future<void> delete(int id) async {
  await isar.writeTxn(() async {
    await isar.users.delete(id);
  });
}

Future<void> clear() async {
  await isar.writeTxn(() async {
    await isar.users.clear();
  });
}

複数データの取得はfindAllで全データを取得します。 保存されているデータ量が多い場合はgetメソッドも用意して、指定Idのみのデータを取得するメソッドも必要そうです。 指定データの削除は紐づくIdで削除もできます。

まとめ

ここでは具体的な使い方を紹介しましたが、Isarを利用しての感想はIsar Inspectorが非常に便利で使いやすいということでした。 機能が豊富で全ての機能を使いきれていないのですが、Isar Inspectorでプロパティ書き換えができるのはとても検証しやすくなると思います。 まだまだ紹介しきれていない機能もありますので、是非調べてみてIsarを導入してみてはいかがでしょうか。