[開発者日記] タスクメモアプリ開発 9日目
9日目の投稿がだいぶ遅れました。
最近、やりたいことが多すぎてあれもこれもしていたらあっという間に時間がなくなりました。高速道路の仕組みやナンバリングについて調査したり、ポケモンではらだいこマリルリを育成したり、彼女とお出かけしたりすると日記おろか開発がままならない状況が続いています。
優先順位として、彼女 > 開発 > 資格取得でいかないといけないですね。
平日にいらんことすると自分が本来やりたいことができずに後悔だけが残るので納得できる時間を作れるように調整できたらなと思います。
さて、8日目はGithubとVSCODEの連携と永続化の調査でSQLiteを使用するということになりました。
今日はメモアプリのプロジェクトにSQLiteを実装していきたいと思います。
SQLiteをインストールする
SQLiteを使用するために関連モジュールをインストールします。
モジュールをインストールする際にpubspec.yamlに記述する必要がありますが、ここでpubspec.yamlは何ぞやとなりました。
そもそもYAMLファイルとは?(ザックリ)
YAMLファイルとはファイルの書き方の一つのことで、読み方はヤムルになります。正式名称はYAML Ain’t Markup Languageで、直訳すると「YAML はマークアップ言語ではない」という意味ですね。おもしろい(笑)
改行とインデントで意味を持つみたいです。
じゃあ、pubspec.yamlは?
ここでYAMLファイルはザックリ理解したけれど、Flutterプロジェクトにおけるyamlファイルの役割はなんだろうとなりました。
公式サイトでは、
とありましたので、どうやらpubspec.yamlは必要なパッケージを指定するだけではなく、使用するフォントや画像なども指定できるみたいですね🤔
つまり、プロジェクトで必要なデータやパッケージを管理できる場所という位置づけでしょうか。。
pubspec.yamlにモジュールを追加する
pubspec.yamlがなんとなくわかりましたので、pubspec.yamlにSQLiteに関連するモジュールを追加してあげます。公式を見てみますとSQLiteを使用したかったらsqfliteとpathモジュールを入れてねと書いてありますのでsqfliteとpathをdependenciesの下に追加します。
dependenciesはプロジェクトで使用するパッケージを管理する場所であり、モジュール名を記述する際は半角スペースが2つ必要なことに注意が必要です。
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
# 追加
sqflite:
path
保存すると勝手にインストールしてくれます。
[memo_app] flutter pub get
Running "flutter pub get" in memo_app... 5.9s
exit code 0
exit code 0 なのでどうやら成功したみたいですね☺
あえてモジュール名を間違えて、失敗したときの挙動を見たいと思います。
sqfliteをsqfliteeeeeeでインストールしてみます。
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
# 追加
# あえて間違える
sqfliteeeeee:
path:
編集して保存してみますと、
[memo_app] flutter pub get
Running "flutter pub get" in memo_app...
Because memo_app depends on sqfliteeeeee any which doesn't exist (could not find package sqfliteeeeee at https://pub.dartlang.org), version solving failed.
pub get failed (server unavailable) -- attempting retry 1 in 1 second...
Because memo_app depends on sqfliteeeeee any which doesn't exist (could not find package sqfliteeeeee at https://pub.dartlang.org), version solving failed.
省略
こんな感じでsqfliteeeeeeというパッケージが見つからんよとひたすら怒られ続けることが確認できました👍
SQLiteを実装する
よし!SQLiteが使用できる環境が整ったから後は書くだけ!
と思いましたが、どこに何を書くのだろうと思い手が止まってしまいました。公式も特に一つのファイルに書き出すって感じなのでとりあえず1ファイルにドカドカっと記述していきます。
Modelを作成する
DBのTableからデータを使用するためにModelを作成します。
Tableにデータを挿入・更新するためにModelからMapに変換する必要があるため、ToMapメソッドを定義します。
class Task {
final int id;
final String task;
const Task({required this.id, required this.task});
Map<String, dynamic> toMap() {
return {
'id': id,
'task': task,
};
}
}
DB・Tableを作成する
Modelを作成したらDB・Tableを作成します。記述コードは、
final database = openDatabase(
# DBのパス
join(await getDatabasesPath(), 'Task_database.db'),
# Table作成 DBを開く前にDBのパスがなければ実行される
onCreate: (db, version) {
return db.execute(
'CREATE TABLE tasks(id INTEGER PRIMARY KEY, task TEXT)',
);
},
# DBのバージョン
version: 1,
);
こんな感じです。
DB名は"task_database.db"で、Table名は"tasks"で作成します。
openDatabase(path, onCreate, version)メソッドを実行させることでデータベースを参照することができます。
openDatabaseをもっと詳しく知りたい場合は公式を参考にしてください。
openDatabaseの第一引数(DBパス)を作成する際に、getDtabasesPath()を使用しています。
どこに作成されるかは公式で記述されていました。
今回はiOS専用で作成しますので、iOSではDocumentsフォルダにDBが保存されるようです。今回のメモアプリではDocumentsフォルダをユーザが参照できる想定がありませんので別にここに保存されても問題ないかと思います。最初、Documentsフォルダは何だっけとなりましたが、
こちらが大変参考になりました。
CRUDを作成する
テーブルのデータを操作するためにCRUDを作成します。
データを挿入・更新では定義したModelをMapに変換させて処理をします。
一方、テーブルからデータを取得する際にはMapからModelに変換させてUI側で利用できる形に変換します。
// データ挿入
Future<void> insertTask(Task task) async {
final db = await database;
await db.insert(
'tasks',
task.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
// データを更新
Future<void> updateTask(Task task) async {
final db = await database;
await db.update(
'tasks',
task.toMap(),
where: 'id = ?',
whereArgs: [task.id],
);
}
// データ全取得
Future<List<Task>> tasks() async {
final db = await database;
final List<Map<String, dynamic>> maps = await db.query('tasks');
return List.generate(maps.length, (i) {
return Task(
id: maps[i]['id'],
task: maps[i]['task'],
);
});
}
// データを削除
Future<void> deleteTask(int id) async {
final db = await database;
await db.delete(
'tasks',
where: 'id = ?',
whereArgs: [id],
);
}
ファイルの配置が気になる
ちょっとしたコードですがやはりコード数が長くなり見にくいかなと思ったので、どうやって配置するとか調べるとGithubにsqfliteのサンプルが公開されていました。しかし、ちょっとめんどくさいので次回にやろうかなと思います。一応忘れないために参考URLを貼っておきます。
まとめ
今回はSQLiteを使用するために、パッケージをインストールしてCRUDを定義しました。次回は他の人が実装しているファイル配置を真似しようかなと思います。
(できればテーブルから取得したデータを表示できたら尚良し)
ここまで読んでいただきありがとうございました🥹
溢れた参考URLたち
日記に盛り込めなかった参考URLたちです。日記を更新するときに盛り込みます。
この記事が気に入ったらサポートをしてみませんか?