セットアップ
Driftは、DartやFlutterアプリケーション用の強力なデータベースライブラリです。 型安全なSQLクエリ、データベースの検証、マイグレーションなどの高度な機能をサポートするために、コンパイル時に実行されるビルダーとコマンドラインツールを使用しています。
これは、セットアップが単に依存関係をpubspec
に追加するだけではありません。
このページでは、プロジェクトへのDriftの追加方法と、次のステップへのポイントを説明します。
Driftの追加に行き詰まったり、プロジェクトに関する質問やフィードバックがある場合は、Githubでディスカッションを開始してコミュニティと共有してください。
もし、インスピレーションを得るためにサンプルアプリを見たいのであれば、Driftを使ったクロスプラットフォームのFlutterアプリがDriftリポジトリの一部として利用可能です。
依存関係
まず、プロジェクトのpubspec.yaml
にDriftを追加します。
核となるdriftの依存関係に加えて、デバイス上の適切なデータベースの場所を見つけるためのパッケージと、driftで最もよく使われるデータベースであるsqlite3
の最新バージョンを含めるためのパッケージも追加します。
dependencies:
drift: ^2.14.0
sqlite3_flutter_libs: ^0.5.0
path_provider: ^2.0.0
path: ^1.8.3
dev_dependencies:
drift_dev: ^2.14.0
build_runner: ^2.4.7
バージョンは各々最新のものを調べて使用してください
なぜこれほど多くのパッケージが必要なのか不思議に思っている方のために、各パッケージが何をするのかを簡単に説明します:
drift
: Driftデータベースへのアクセスに使用するAPIを定義したコアパッケージsqlite3_flutter_libs
: AndroidまたはiOSアプリに最新のsqlite3
バージョンを同梱します。 Flutterを使用していない場合は必要ありませんが、その場合は自身でsqlite3
を含める必要があります。 他のプラットフォームについての概要は、対応プラットフォームを参照してください。sqlite3_flutter_libs
パッケージは、armv8
、armv7
、x86
、x86_64
のアーキテクチャ用にネイティブsqlite3ライブラリを含むことに注意してください。 Flutterアプリは、さらなる設定無しに32ビットのx86
デバイス上では実行されないので、x86
ビルドが不要な場合は、build.gradle
にコードを追加すべきです。 そうしないと、Play Storeがx86
デバイスのユーザーに対しても、サポートされていないアプリのインストールを許可してしまう可能性があります。 現在のFlutterのネイティブビルドシステムでは、残念ながらDriftはこれを代わりに行うことはできません。path_provider
とpath
: データベースを保存するのに適した場所を探すのに使われます。FlutterとDartチームによって管理されています。drift_dev
: この開発専用のパッケージは、テーブルに基づいてクエリコードを生成します。最終的なアプリには含まれません。build_runner
: Dartチームによって保守されているコード生成のための共通ツール。
データベースクラス
Driftを使用するすべてのプロジェクトには、データベースにアクセスするためのクラスが少なくとも1つ必要です。
このクラスは使用するすべてのテーブルを参照し、Driftのコードジェネレータの中心的なエンドポイントになります。
この例では、このデータベースクラスはdatabase.dart
というファイルでlib/
の下のどこかで定義されていると仮定します。
もちろん、このクラスは好きなDartファイルに置くことができます。
データベースを便利にするために、簡単なテーブルも追加します。このテーブルTodoItems
は、TodoリストアプリのTodo項目を保存するのに使用します。
Dartでテーブルを定義する方法については、Dartテーブルのページで説明しています。SQLを使ってテーブルを定義したい場合もサポートしています!
SQL APIについてはこちらを参照してください。
ひとまず、database.dart
の中身は以下のとおり:
import 'package:drift/drift.dart';
part 'database.g.dart';
class TodoItems extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text().withLength(min: 6, max: 32)();
TextColumn get content => text().named('body')();
IntColumn get category => integer().nullable()();
}
(tables: [TodoItems])
class AppDatabase extends _$AppDatabase {
}
part
文とextends _$AppDatabase
でアナライザの警告が表示されます。
これはDriftのジェネレータがまだ実行されていないためです。
build_runnerを起動することで実行できます。
dart run build_runner build
は必要なコードを一度にすべて生成しますdart run build_runner watch
はソースの変更を監視し、インクリメンタルビルドでコードを生成します。これは開発セッションに適しています
いずれかのコマンドを実行すると、生成された_$AppDatabase
クラスを含むdatabase.g.dart
ファイルが生成されます。
オーバーライドの欠落とコンストラクタの欠落に関するエラーが表示されます。コンストラクタは、Driftにデータベースを開く方法を指示します。
schemaVersion
はデータベースを変更した後のマイグレーションに関係するので、今は1
のままにしておきます。
データベースクラスは次のようになります:
// これらのインポートはsqlite3データベースを開くのに必要です
import 'dart:io';
import 'package:drift/native.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
import 'package:sqlite3/sqlite3.dart';
import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart';
// ... TodoItemsテーブルの定義は同じままです
(tables: [TodoItems])
class AppDatabase extends _$AppDatabase {
AppDatabase() : super(_openConnection());
int get schemaVersion => 1;
}
LazyDatabase _openConnection() {
// LazyDatabase ユーティリティは、ファイルの正しい位置を非同期で見つけることを可能にします。
return LazyDatabase(() async {
// こちらのデータベースファイルである db.sqliteをアプリのドキュメントフォルダに配置してください。
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'db.sqlite'));
// 古いAndroidバージョンの制限を回避する処理を行ってください
if (Platform.isAndroid) {
await applyWorkaroundToOpenSqlite3OnOldAndroidVersions();
}
// SQLite3の一時ファイルの保存場所をより適切に選択するようにしてください
// システムからの場所はサンドボックス化のためアクセスできない可能性があります。
final cachebase = (await getTemporaryDirectory()).path;
// Androidでは/tmpにアクセスできません。これはsqlite3がデフォルトで試みる場所です。
// 正しい一時ディレクトリについて明示的に指示してください。
sqlite3.tempDirectory = cachebase;
return NativeDatabase.createInBackground(file);
});
}
Android特有の回避策が必要なのは、sqlite3がUNIX系システムで/tmp
を使用して個人データを保存しようとするためであり、これはAndroidでは禁止されています。
また、この機会を利用して、古いAndroidデバイスの一部がdart.ffi
を通じてカスタムライブラリをロードする際に抱える問題を回避します。
次のステップ
おめでとうございます! このセットアップが完了すると 、プロジェクトはDriftを使用する準備が整います。 以下の短いコードは、データベースを開く方法と、挿入や選択を実行する方法を示しています:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final database = AppDatabase();
await database.into(database.todoItems).insert(TodoItemsCompanion.insert(
title: 'todo: finish drift setup',
content: 'We can now write queries and define our own tables.',
));
List<TodoItem> allItems = await database.select(database.todoItems).get();
print('items in database: $allItems');
}
しかし、Driftはもっと色々できます! 以下のページでは、Driftを始めるときに役立つ情報をご紹介します。
- Dartテーブル: このページでは、独自のDartテーブルを作成する方法と、そのためにDriftが生成するクラスについて説明します。
- クエリを書く: Driftが生成するクラスは、selectやinsert、update、deleteといった最も一般的なSQL文の作成をサポートします。
- 後々のために: 新しい絡むやテーブルを追加するなどしてデータベースを変更する場合、既存のデータベースを新しいフォーマットに変換するためのマイグレーションを作成する必要があります。Driftの豊富なマイグレーションツールがその手助けをしてくれます。