Flutterでのローカルデータベース管理:Driftパッケージの紹介

flutter

はじめに

Flutter開発者として、ローカルデータベースの操作はアプリケーションのパフォーマンスとユーザーエクスペリエンスに大きく影響します。この記事では、この課題を解決する助けとなるパッケージ、Driftについて紹介します。

参照)Driftパッケージ:https://drift.simonbinder.eu/

Driftとは何か?

Driftは、FlutterおよびDart向けのリアクティブな永続的データベースライブラリで、SQLiteデータベースとの対話を容易にするツールセットを提供します。コンパイル時の安全性、強力なSQLサポート、そして非同期プログラミングを含む一連の機能が特徴です。

Driftの主な特徴

  1. コンパイル時の安全性: DriftはSQLクエリの誤りをコンパイル時に検出します。これにより、ランタイムエラーを大幅に減らすことができます。
  2. 強力なSQLサポート: Driftは、クエリを直接記述するための強力なSQLサポートを提供します。これにより、複雑なクエリや結合を簡単に行うことができます。
  3. 非同期プログラミング: Driftは、Dartの非同期プログラミングをフルにサポートしています。これにより、データベース操作をスムーズに行うことができます。

Driftのセットアップと使い方

ここからはDriftのセットアップと使い方を紹介します
公式の方法を参考にして、紹介します

セットアップ

flutterのプロジェクトの作成に関しては、下記に記載していますのでこちらを参考にしてください

初めてのFlutter/Dartマルチプラットフォームアプリ開発チュートリアル
はじめに FlutterはGoogleが開発した、マルチプラットフォームのモバイルアプリ開発のフレームワークです。Flutterを使うと、AndroidとiOSの両方のプラットフォームで同時にアプリを開発することができます。 また、ブラウザ...

Driftをプロジェクトに追加するには、pubspec.yamlファイルに以下を追記します:

dependencies:
  drift: ^2.8.0
  sqlite3_flutter_libs: ^0.5.0
  path_provider: ^2.0.0
  path: ^1.8.3

dev_dependencies:
  drift_dev: ^2.8.0
  build_runner: ^2.3.3

その後、flutter pub getを実行してパッケージを取得します。

path_providerとpathについては、sqliteのファイルをプロジェクトに適した場所に配置するために必要なのでデフォルトでも問題ない場合は必要ないです
build_runnerについてはコード生成のために必要になります。

テーブルの作成

次にテーブルを定義するクラスを作成します。今回は例としてusersテーブルを作成してみます

class Users extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get name => text().withLength(min: 1, max: 50)();
  DateTimeColumn get birthday => dateTime().nullable()();
}

ここでは、idは自動採番、nameは50文字までの文字列、birthdayはDateTime型でNullを許容する誕生日を定義しています
細かなデータ定義に関してはこちらに載っていますが、初期値やPrimary key、外部キー、ユニークなカラムなどRDBに必要な絡む定義は一通り揃っています。そのほかにもDartのEnumを利用したカラムの定義も行うことができます

※Enumについてはこちら

Flutter/DartでEnum(列挙型)を使う:コードの保守性と可読性を向上させる
この記事では、Flutter開発でEnumとExtensionを活用する方法とその利点について解説します。コードの可読性、保守性、再利用性を向上させ、効率的なアプリ開発を実現しましょう。

データベースの定義

次にデータベース定義のクラスを作ります

import 'package:drift/drift.dart';

part 'my_database.g.dart';
@DriftDatabase(tables: [Users])
class MyDatabase extends _$MyDatabase {
  MyDatabase() : super(FlutterQueryExecutor.inDatabaseFolder(path: 'db.sqlite'));

  @override
  int get schemaVersion => 1;
}

このクラスでは、@DriftDatabase(tables: [Users]) をつけることで先ほど作成したUsersがデータベースのテーブルとして認識されます。新しい、テーブルを追加する場合にもtablesの配列に追加していきます。

part 'my_database.g.dart'; については、コードを書いた段階ではコンパイルエラーになりますが、セットアップで追加したbuild_runnerを使うことでmy_database.g.dartが自動生成され、コンパイルエラーがなくなります。

schemaVersionについては、アプリケーションのデータベースバージョンが上がるごとに2、3、、、とあげていき、マイグレーションの際に利用することができます。

FlutterQueryExecutor.inDatabaseFolder(path: 'db.sqlite')は作成されるsqliteのファイルを作成する場所を指定できます。Flutterデフォルトのデータベースフォルダにdb.sqliteというファイルが作成され、DBのデータが追加されていきます

このファイルを追加した後は、下記コマンドを実行して自動生成ファイルを作成してください

flutter pub run build_runner

データの登録

次は作成したusersテーブルにデータを登録してみます

final db = MyDatabase();
final user = UsersCompanion(
  name: Value("Alice"),
  birthday: Value(DateTime(2000, 1, 1)),
);

await db.into(db.users).insert(user);

このコードでは先ほど作成した、usersテーブルにデータを登録しています。
UsersCompanionというのは、Driftが自動生成したコードでinsertする際に使います。idを指定していないので自動的に1,2,3,,,と採番がされていきます。

データの取得

次はusersテーブルのデータを取得します

final users = await db.select(db.users).get();

ここではusersテーブルのレコードを全て取得します。

1レコードのみ取得したい場合は、getSingle()を利用すると1レコードのみが取得できます。

取得したusersテーブルのデータは自動生成されたコードのUsersDataというクラスのデータになります。

ほかにもdeleteやupdateはもちろん、selectなどでよく利用するwhereやjoin、order byなども当然あります。

まとめ

Driftは強力な機能を備えたローカルデータベース管理パッケージで、Flutterアプリケーションでのデータ操作を容易にします。そのコンパイル時の安全性、強力なSQLサポート、そして非同期プログラミングのサポートにより、データベース操作を効率的に行うことが可能です。

Flutterアプリでのデータ管理を考えている方はぜひ試してみてください。