自分用に書いたメモです。
間違っている部分やおかしな部分があったらコメントください!
この記事を書くにあたってこちらの2つのサイトを参考にさせていただきました。
・FlutterのシンプルなSQFliteデータベースの例
・Flutterでsqliteを使ったTodoアプリを作る
パッケージ
・sqflite
・path_provider
・uuid
pubspec.yaml
sqflite: ^2.0.0
path_provider: ^2.0.2
uuid: ^3.0.4
モデル
lib/db/memo.dart
import 'package:uuid/uuid.dart';
class Memo {
late int id;
late DateTime date;
late String note;
Memo({
required this.id,
required this.date,
required this.note,
});
Memo.newMemo() {
id = Uuid().v4();
date = DateTime.now();
note = "";
}
// SQLiteではDateTime型を保存できないためString型に変換する
Map<String, dynamic> toMap() => {
"id": id,
// DateTime型を、文字列で保存する。
"date": date.toUtc().toIso8601String(),
"note": note,
};
factory Memo.fromMap(Map<String, dynamic> json) => Memo(
id: json["id"],
// 文字列で保存されているため、DateTime型に変換する。
date: DateTime.parse(json["date"]).toLocal(),
note: json["note"],
);
}
DatabaseProvider
lib/db/dbProvider.dart
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:article_project/db/memo.dart';
class DBProvider {
final _databaseName = 'my_database.db';
final _databaseVersion = 1;
final _tableName = 'memo';
final _columnId = 'id';
final _columnDate = 'date';
final _columnNote = 'note';
DBProvider._();
static final DBProvider instance = DBProvider._();
Database? _database;
// Databaseが存在するかどうか確認して、あったら返す。
Future<Database> get database async {
if (_database != null) return _database!;
// Databaseがない場合に作成する。
_database = await _initDatabase();
return _database!;
}
Future<Database> _initDatabase() async {
Directory documentDirectory = await getApplicationDocumentsDirectory();
String path = join(documentDirectory.path, _databaseName);
return await openDatabase(
path,
version: _databaseVersion,
onCreate: _onCreate,
);
}
Future<void> _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $_tableName (
$_columnId TEXT PRIMARY KEY,
$_columnDate TEXT NOT NULL,
$_columnNote TEXT NOT NULL
)''');
}
Future<int> insert(Memo row) async {
Database db = await instance.database;
return await db.insert(_tableName, row.toMap());
}
Future<List<Memo>> getAllRows() async {
Database db = await instance.database;
var res = await db.query(_tableName);
// Databaseの中身を確認して、あった場合Listにして無い場合は空のListを返す。
List<Memo> list =
res.isNotEmpty ? res.map((m) => Memo.fromMap(m)).toList() : [];
return list;
}
Future<Memo?> getSelectRow(String id) async {
Database db = await instance.database;
List<Map> maps = await db.query(_tableName,
columns: [_columnId, _columnDate, _columnNote],
where: '$_columnId = ?',
whereArgs: [id]);
if (maps.isNotEmpty) {
return Memo.fromMap(Map<String, dynamic>.from(maps.first));
}
return null;
}
Future<int> update(Memo row) async {
Database db = await instance.database;
return await db.update(
_tableName,
row.toMap(),
where: '$_columnId = ?',
whereArgs: [row.id],
);
}
Future<int> delete(String id) async {
Database db = await instance.database;
return await db.delete(
_tableName,
where: '$_columnId = ?',
whereArgs: [id],
);
}
}
Main
main.dart
import 'package:flutter/material.dart';
import 'package:uuid/uuid.dart'; // ++
import 'package:my_project/db/memo.dart'; // ++
import 'package:my_project/db/dbProvider.dart'; // ++
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// int _counter = 0;
// void _incrementCounter() {
// setState(() {
// _counter++;
// });
// }
final dbProvider = DBProvider.instance; // ++
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
/** --- 追加 ここから --- **/
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
child: Text(
'insert',
style: TextStyle(fontSize: 20),
),
onPressed: _insert,
),
ElevatedButton(
child: Text(
'query',
style: TextStyle(fontSize: 20),
),
onPressed: _query,
),
ElevatedButton(
child: Text(
'update',
style: TextStyle(fontSize: 20),
),
onPressed: _update,
),
ElevatedButton(
child: Text(
'delete',
style: TextStyle(fontSize: 20),
),
onPressed: _delete,
),
],
),
),
/** --- 追加 ここまで -- **/
// body: Center(
// child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
// children: <Widget>[
// Text(
// 'You have pushed the button this many times:',
// ),
// Text(
// '$_counter',
// style: Theme.of(context).textTheme.headline4,
// ),
// ],
// ),
// ),
// floatingActionButton: FloatingActionButton(
// onPressed: _incrementCounter,
// tooltip: 'Increment',
// child: Icon(Icons.add),
// ),
);
}
/** --- 追加 ここから --- **/
void _insert() async {
Memo row = Memo.newMemo();
row.note = 'test Text 000';
final id = await dbProvider.insert(row);
print('inserted row id: $id');
}
void _query() async {
final allRows = await dbProvider.getAllRows();
print('query all rows:');
allRows.forEach(print);
}
void _update() async {
final rowsAffected = await dbProvider.update(Memo.newMemo());
print('updated $rowsAffected row(s)');
}
void _delete() async {
String uuid = Uuid().v4();
final rowsDeleted = await dbProvider.delete(uuid);
print('deleted $rowsDeleted row(s): row $uuid');
}
/** --- 追加 ここまで --- **/
}