Iganinのブログ

日頃の開発で学んだ知見を中心に記事を書いています。

FlutterでローカルDBを扱う方法

はじめに

FlutterでローカルDBを扱う方法について、 sqflite を使用したsqliteデータベースを扱うやり方を記載します。

環境設定

以下の環境を使用しています。

flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v1.0.0, on Mac OS X 10.14 18A391, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK 28.0.2)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.0)
[✓] Android Studio (version 3.2)
[✓] VS Code (version 1.30.1)

導入方法

sqlite3用のライブラリとPath設定を行うためのライブラリを導入します。 pubspec.yamlに以下の記述を行います。 anyとし、バージョンの指定を行っていませんが、必要に応じてVersion指定を行ってください。

dependencies:
  flutter:
    sdk: flutter

  sqflite: any
  path_provider: any

DBを使用するクラスのimport文にpath_providerとsqfliteを追加します。 DBのインタンス生成は openDatabase()メソッドを使用して行います。 ここで optionのパラメータとしてversionを指定することができ、 onUpgrade, onDowngradeの実行を行うかどうかの判断に使われます。

また、Databaseで使用できるデータ型は限定されているため注意が必要です。 例えばbool型は存在ないしないため、 INTEGERなどに適宜読み換える必要があります。(0 false, 1 trueなど)

import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
import 'dart:async';
import 'dart:io';

class DbProvider {
  // DBのインスタンスはDatabaseで定義します
  Database db;

  // Pathの取得およびDBを開く処理は非同期のため初期化処理をasyncで囲みます。
  // Pathはsqflite の getDatbasePath()でも取得することができます。
  void init() async {
    Directory documentDirectory = await getApplicationDocumentsDirectory();
    final path = join(documentDirectory.path, "sample.db");
    
    // openDatabaseメソッドを使用することでDBインスタンスを取得することができます。
    db = await openDatabase(
        path,
        version: 1,
        onCreate: (Database newDb, int version) {
        // DBがpathに存在しなかった場合に onCreateメソッドが呼ばれます。
        // このタイミングでTableの生成などを行います。
        // db.executeでSQL文の実行を行うことができます。
        // なお、DBに指定できるプロパティは 
        // INTEGER(int)、TEXT(String)、REAL(num)、BLOB(List<int>)のみになるため注意が必要です。
          newDb.execute("""
            CREATE TABLE Sample
              (
                id INTEGER PRIMARY KEY,
                text TEXT,
                time INTEGER
              )
            """);
        },
    );
  }

メソッド

// DB削除
deleteDatabase(path: Path)

// Insert
insert(String table, Map<String, dynamic> values,
      {String nullColumnHack, ConflictAlgorithm conflictAlgorithm});

// 例 追加された件数が関数の実行結果として返却されます
final addedCount = await db.insert("Sample", map);

// Update
  void update(String table, Map<String, dynamic> values,
      {String where,
      List<dynamic> whereArgs,
      ConflictAlgorithm conflictAlgorithm});

// 例
    db.update(
        "Sample",
        map,
      where: "id = ?",
      whereArgs: [id],
    )


// Delete
  void delete(String table, {String where, List<dynamic> whereArgs});

// 例 返却値として削除した件数が返却されます。
    final deletedCount = await db.delete(
      "Sample",
      where: "id = ?",
      whereArgs: [id],
    );

// Get
  Future<List<Map<String, dynamic>>> query(String table,
      {bool distinct,
      List<String> columns,
      String where,
      List<dynamic> whereArgs,
      String groupBy,
      String having,
      String orderBy,
      int limit,
      int offset});

// 例 whereで条件の指定。?でパラメータ。whereArgsでパラメータの指定を行います。
    final maps = await db.query(
      "Sample",
       columns: null,
      where: "id = ?",
      whereArgs: [id],
      groupBy: "time",
      limit: 30,
      offset: 5
   );

参考文献