Blog スタッフブログ

Flutter システム開発

[Flutter]FlutterでSQLiteを利用する

こんにちは、株式会社MIXシステム開発担当のBloomです。

今回はFlutterからSQLiteを利用する方法について、お仕事の中で得た知見を共有させていただきたいと思います。

まずはいつも通りパッケージを導入しましょう。

flutter pub add sqflite

では、まずはモデルクラスを実装しましょう。

class Item {
  final int? id;
  final String name;
  final int number;

  Item({this.id, required this.name, required this.number});

  factory Item.fromMap(Map<String, dynamic> map) {
    return Item(
      id: map['id'],
      name: map['name'],
      number: map['number'],
    );
  }

  Map<String, dynamic> toMap() {
    final map = {
      'name': name,
      'number': number,
    };
    if (id != null) {
      map['id'] = id as Object;
    }
    return map;
  }
}

次にデータベースアクセスをラップするヘルパークラスを作りましょう。

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'item.dart';

class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  factory DatabaseHelper() => _instance;
  DatabaseHelper._internal();

  static Database? _database;

  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDataBase('app.db');
    return _database!;
  }

  Future<Database> _initDataBase(String fileName) async {
    final dbPath = await getDatabasesPath();
    final path = join(dbPath, fileName);

    return await openDatabase(
      path,
      version: 1,
      onCreate: _onCreate,
    );
  }

  // ここでテーブルの作成を行っています。
  Future<void> _onCreate(Database db, int version) async {
    await db.execute('''
      CREATE TABLE items (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT,
        number INTEGER
        )
    ''');
  }

  // 挿入
  Future<int> insertItem(Item item) async {
    final db = await database;
    return await db.insert('items', item.toMap());
  }

  // 全取得
  Future<List<Item>> getItems() async {
    final db = await database;
    final List<Map<String, dynamic>> maps = await db.query('items', orderBy: 'id DESC');
    return maps.map((map) => Item.fromMap(map)).toList();
  }

  // 更新
  Future<int> updateItem(Item item) async {
    final db = await database;
    return await db.update(
      'items',
      item.toMap(),
      where: 'id = ?',
      whereArgs: [item.id],
    );
  }

  // 削除
  Future<int> deleteItem(int id) async {
    final db = await database;
    return await db.delete('items', where: 'id = ?', whereArgs: [id]);
  }
}

では、実際に利用してみましょう。サンプルアプリのカウンター部分へデータベースを組み込んでみます。

import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'databaseHelper.dart';
import 'item.dart';


class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  @override
  void initState() {
    super.initState();
    _initCounter();
  }

  Future<void> _initCounter() async {
    final db = DatabaseHelper();
    final items = await db.getItems();
    try {
      setState(() {
        _counter = items.first.number;
      });
    } catch (e) {
      setState(() {
        _counter = 0;
      });
    }
  }

  void _incrementCounter() {
    setState(()  {
      _counter++;
      _updateItem();
    });
  }

  Future<void> _updateItem() async {
    final db = DatabaseHelper();
    final items = await db.getItems();
    try {
      var item = items.first;
      final updatedItem = Item(id: item.id, name: item.name, number: _counter);
      await db.updateItem(updatedItem);
    } catch (e) {
      await db.insertItem(Item(name: "name", number: _counter));
    }
  }

}

これだけでsqliteを組み込むことができました。良かったですね。

参考文献

sqflite | Flutter package – pub.dev