📑
【Flutter】SQLiteでデータベースを組み込む方法
使用するライブラリ
データベースを組み込む方法
1. アセットの準備
まず、プロジェクトにデータベースファイルを追加します。
assets/example.db
pubspec.yaml
にアセットを登録します:
pubspec.yaml
flutter:
assets:
- assets/example.db
2. データベースの実装パターン
パフォーマンス重視の実装
初回起動時のみデータベースをコピーする方法です。
performance_database.dart
// データベースを初期化する関数
Future<Database> initPerformanceDatabase() async {
// データベースのパスを取得
var databasesPath = await getDatabasesPath();
var path = join(databasesPath, "demo_asset_example.db");
// データベースの存在確認
var exists = await databaseExists(path);
if (!exists) {
print("新規データベースをコピーします");
try {
// 親ディレクトリの作成
await Directory(dirname(path)).create(recursive: true);
// アセットからコピー
ByteData data = await rootBundle.load(url.join("assets", "example.db"));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
// データベースファイルの書き込み
await File(path).writeAsBytes(bytes, flush: true);
} catch (e) {
print("エラーが発生しました: $e");
}
}
// データベースを開く
return await openDatabase(path, readOnly: true);
}
毎回新規コピーする実装
アプリ起動時に必ず新しいデータベースをコピーする方法です。既存のデータベースを削除する手順が必要です。
fresh_copy_database.dart
// 毎回新しいデータベースをコピーする関数
Future<Database> initFreshDatabase() async {
var databasesPath = await getDatabasesPath();
var path = join(databasesPath, "demo_fresh_copy.db");
// 既存のデータベースを削除
await deleteDatabase(path);
try {
// ディレクトリ作成
await Directory(dirname(path)).create(recursive: true);
// アセットからコピー
ByteData data = await rootBundle.load(url.join("assets", "example.db"));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await File(path).writeAsBytes(bytes, flush: true);
} catch (e) {
print("エラーが発生しました: $e");
}
return await openDatabase(path, readOnly: true);
}
バージョン管理機能付きの実装
データベースのバージョンを管理する方法です。
既存 DB と AssetDB の Version を比較して、DB を追加・変更したい場合に使用する。
versioned_database.dart
// バージョン管理付きデータベース初期化関数
Future<Database> initVersionedDatabase({
required String databasesPath,
required String versionNumFilename,
required String dbFilename
}) async {
var dbPath = join(databasesPath, dbFilename);
var versionNumFile = File(join(databasesPath, versionNumFilename));
// 現在のバージョン確認
var existingVersionNum = 0;
if (versionNumFile.existsSync()) {
existingVersionNum = int.parse(await versionNumFile.readAsString());
}
// アセットのバージョン取得
var assetVersionNum = int.parse(
(await rootBundle.loadString(url.join('assets', versionNumFilename))).trim()
);
// バージョン比較とコピー
if (existingVersionNum < assetVersionNum) {
try {
await Directory(databasesPath).create(recursive: true);
var data = await rootBundle.load(url.join('assets', dbFilename));
var bytes = Uint8List.sublistView(data);
await File(dbPath).writeAsBytes(bytes, flush: true);
await versionNumFile.writeAsString('$assetVersionNum', flush: true);
} catch (e) {
print("エラーが発生しました: $e");
}
}
return await openDatabase(dbPath);
}
使い分けのポイント
-
パフォーマンス重視の実装
- メモリ使用量を最小限に抑えたい場合
- データベースの更新頻度が低い場合
-
毎回新規コピーの実装
- 常に最新のデータを使用したい場合
- テスト環境で使用する場合
-
バージョン管理機能付きの実装
- アプリのアップデートでデータベースも更新する場合
- データベースの変更履歴を管理したい場合
参照
Discussion