Flutter で、ローカルデータベースにデータを保存する方法を紹介します!
SQLite を扱う sqflite のパッケージを使用していきます。
パッケージのインストール
sqflite のパッケージをインストールします。また、path パッケージも併せてインストールします。
パッケージのインストール方法は、以下の記事をご参照ください。
データベースの操作方法
データベースの操作には、データの取得、追加、更新、削除があります。
データベースの作成
まずは、操作するデータベースを作成します。
以下のように、データベース名やテーブル名、構成を指定します。
Future<Database> initDatabase() async {
String path = join(await getDatabasesPath(), "my_database.db");
return await openDatabase(
path,
version: 1,
onCreate: (Database db, int version) async {
await db.execute('''
CREATE TABLE my_table(
id INTEGER PRIMARY KEY,
title TEXT,
is_finish INTEGER
)
''');
},
);
}
全データの取得
データベースに保存されている全データを取得するには、以下のように query を使用します。
Future<List<Map<String, dynamic>>> getAllData() async {
final Database? db = await database;
return await db!.query('my_table');
}
データの追加
データベースにデータを追加するには、以下のように、追加するデータを指定して insert を使用します。
Future<void> insertData(Map<String, dynamic> data) async {
final Database? db = await database;
await db!.insert('my_table', data, conflictAlgorithm: ConflictAlgorithm.replace);
}
データの更新
データの更新を行うには、以下のように、更新するデータの id と更新後のデータを指定して update を使用します。
Future<int> updateData(int id, Map<String, dynamic> data) async {
final Database? db = await database;
return await db!.update('my_table', data, where: 'id = ?', whereArgs: [id]);
}
データの削除
データを削除するには、以下のように、削除するデータの id を指定して delete を使用します。
Future<int> deleteData(int id) async {
final Database? db = await database;
return await db!.delete('my_table', where: 'id = ?', whereArgs: [id]);
}
使用例
sqflite を使用したアプリの例として、ToDo アプリを作成してみました。
構成は、以下の3つのファイルになっています。
- database_helper.dart
データベース操作を管理するファイル - todo.dart
ToDo のクラスファイル - todo_view.dart
ToDo をリストで表示するページを作成するファイル
database_helper の作成
データベースの作成、操作を行う database_hepler は、以下のようになっています。
DatabaseHelper クラスとして、シングルトンで実装しています。
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static final DatabaseHelper _instance = DatabaseHelper._internal();
factory DatabaseHelper() {
return _instance;
}
DatabaseHelper._internal();
static Database? _database;
Future<Database?> get database async {
if (_database != null) {
return _database;
}
_database = await initDatabase();
return _database;
}
Future<Database> initDatabase() async {
String path = join(await getDatabasesPath(), "my_database.db");
return await openDatabase(
path,
version: 1,
onCreate: (Database db, int version) async {
await db.execute('''
CREATE TABLE my_table(
id INTEGER PRIMARY KEY,
title TEXT,
is_finish INTEGER
)
''');
},
);
}
Future<List<Map<String, dynamic>>> getAllData() async {
final Database? db = await database;
return await db!.query('my_table');
}
Future<void> insertData(Map<String, dynamic> data) async {
final Database? db = await database;
await db!.insert('my_table', data, conflictAlgorithm: ConflictAlgorithm.replace);
}
Future<int> updateData(int id, Map<String, dynamic> data) async {
final Database? db = await database;
return await db!.update('my_table', data, where: 'id = ?', whereArgs: [id]);
}
Future<int> deleteData(int id) async {
final Database? db = await database;
return await db!.delete('my_table', where: 'id = ?', whereArgs: [id]);
}
}
ToDo クラスの作成
ToDo タスクの構成をクラスとして実装したのが、以下の todo.dart になります。
今回は、ToDo が、id とタイトル、完了済みかどうかの情報を持つようにしました。
また、データベースに保存するために Map に変換するメソッドと、データベースから ToDo 構築するために ToDo クラスへの変換を行うメソッドも用意しています。
class ToDo {
final int? id;
final String title;
final bool isFinish;
ToDo({
this.id,
required this.title,
required this.isFinish,
});
Map<String, dynamic> toMap() {
return {
'id': id,
'title': title,
'is_finish': isFinish ? 1 : 0,
};
}
factory ToDo.fromMap(Map<String, dynamic> map) {
return ToDo(
id: map['id'],
title: map['title'],
isFinish: map['is_finish'] == 1,
);
}
}
ToDo リストとして表示するページを作成
ToDo リストとして表示するページは、以下のように実装しています。
データベースの操作を行なった際には、_fetchToDoList() でデータベースの更新内容をページに反映させるようにしています。
import 'package:flutter/material.dart';
import 'database_helper.dart';
import 'todo.dart';
class TodoListPage extends StatefulWidget {
const TodoListPage({Key? key}) : super(key: key);
@override
State<TodoListPage> createState() => _TodoListPageState();
}
class _TodoListPageState extends State<TodoListPage> {
late List<ToDo> _todoList;
DatabaseHelper dbHelper = DatabaseHelper();
@override
void initState() {
super.initState();
_todoList = [];
_fetchToDoList();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ToDo List'),
),
body: _buildTodoList(),
floatingActionButton: FloatingActionButton(
onPressed: _pushAddTodoScreen,
tooltip: 'Add ToDo',
child: const Icon(Icons.add),
),
);
}
// floatingActionButtonが押された時に表示するToDo追加ページ
void _pushAddTodoScreen() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return Scaffold(
appBar: AppBar(
title: const Text('Add a new ToDo'),
),
body: TextField(
autofocus: true,
onSubmitted: (val) {
ToDo newTodo = ToDo(title: val, isFinish: false);
_insertToDo(newTodo);
Navigator.pop(context);
},
decoration: const InputDecoration(
hintText: 'Input a new ToDo title.',
contentPadding: EdgeInsets.all(16.0)),
),
);
},
),
);
}
// ToDoListの作成
Widget _buildTodoList() {
return ListView.builder(
itemCount: _todoList.length,
itemBuilder: (context, index) {
ToDo todo = _todoList[index];
return Card(
child: ListTile(
title: Text(todo.title),
leading: Checkbox(
onChanged: (value) {
ToDo updatedTodo = ToDo(id: todo.id, title: todo.title, isFinish: value!);
_updateToDo(updatedTodo);
},
value: todo.isFinish,
),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
_deleteToDo(todo);
}
),
),
);
},
);
}
// データベースの内容をページに反映
_fetchToDoList() async {
List<Map<String, dynamic>> result = await dbHelper.getAllData();
setState(() {
_todoList = result.map((map) => ToDo.fromMap(map)).toList();
});
}
_insertToDo(ToDo todo) async {
await dbHelper.insertData(todo.toMap());
_fetchToDoList();
}
_updateToDo(ToDo todo) async {
await dbHelper.updateData(todo.id!, todo.toMap());
_fetchToDoList();
}
_deleteToDo(ToDo todo) async {
await dbHelper.deleteData(todo.id!);
_fetchToDoList();
}
}
実行例
まとめ
Flutter で、ローカルデータベースを使用して、データを永続化させる方法について、紹介しました!
- sqflite パッケージで、ローカルデータベースの実装が可能
- テーブル名や構成を指定してデータベースを生成後、データの取得、追加、更新、削除が可能
以上で、【Flutter】ローカルデータベースにデータを保存(永続化)する方法 は終わりです。
コメント