FlutterとDB(SQLite)の小話。

FlutterとDB

現在公開しておりますアプリを作る際に、最初に現れたある意味強敵です。

アプリの方は

GooglePlay「Nagare」

AppStore「Nagare」

からどうぞどうぞよろしくおねがいします。

さてなぜ強敵だったのか・・・
そして、SQLiteを使うとなにがよろしいのかというお話が主でございます。

SQLの利点。

一番の利点はやはり、データの永続化、そしてそのデータの永続化と
情報の「追加」「更新」「読み込み」に「SQL」がつかえることです。
SQLは、業務システムでもWebのシステムでもよく耳にすることもあろうかと思います。
「SELECT * FROM user WHERE user_id = 'test'」みたいなやつです。
これが使えるのがなにがよろしいか。
自前でファイル実装した際にさて、データの何行目のなんのデータがほしいとなると
結構な苦労がありそうな気配がしますが、SQLであればSELECT条件でスパッと抜けてきます。
これが最大便利なんではないかと考えております。
これをやはり使いたくなってしまうのが、業務系をしてしまっていた私の癖なのかもしれませんが
Androidには「SQLite」と言うファイルベースのSQLエンジンがあるではないですか!
使わない手はありません。

FlutterでSQLiteを使うには

FlutterでSQLiteを利用するには

sqflite

のパッケージを使うのがよろしいでしょう。
ありがたいことにたくさんの有志がたくさんのパッケージを作ってくれているのが
このFlutterの有り難さです。
人の優しさに全力で甘えましょう。自前で作ると地獄を見そうなので。

このパッケージを
Flutterプロジェクト内のファイル
「pubspec.yaml」の「dependencies」のところに追加しましょう。
適切にバージョンも指定しましょう。
2019年10月25日現在、この「sqflite」のバージョンは、「1.1.7+1」ですので指定方法は

sqflite: ^1.1.7+1

になります。
あとはVisualStudioCodeであれば勝手にファイルが落ちてくれるはずですが
様子がおかしい場合は

「flutter pub get 」のコマンドで自分で取得しましょう。

少しだけ覗く

Flutterがなんでマルチデバイス(Android、iOS」を一つのソースでできるのか・・・
その秘密の一端は皆様、有志の方が作ってくれているソースを見ると一端を知ることができます。

https://github.com/tekartik/sqflite

そこには「Android」と「iOS」のディレクトリが存在しています。
中身を見てみると・・・
JavaとObjective-Cのソースが・・・
有志の方々のおかげでFlutterで作る分にはこのソースを意識しないで済んでいます。ありがたいことです。

早速FlutterでSQLiteをしよう

早速実装しようとするとこれが言うことを聞いてくれません。
データベースのオブジェクトが生成される前に、SQL文を発行しようとしてコケるわけです。
なぜだ・・・
以下、公式のサンプルを抜粋してきました

class TodoProvider {
  Database db;
  Future open(String path) async {
    db = await openDatabase(path, version: 1,
        onCreate: (Database db, int version) async {
      await db.execute('''
create table $tableTodo ( 
  $columnId integer primary key autoincrement, 
  $columnTitle text not null,
  $columnDone integer not null)
''');
    });
  }
  Future insert(Todo todo) async {
    todo.id = await db.insert(tableTodo, todo.toMap());
    return todo;
  }
  Future getTodo(int id) async {
    List maps = await db.query(tableTodo,
        columns: [columnId, columnDone, columnTitle],
        where: '$columnId = ?',
        whereArgs: [id]);
    if (maps.length > 0) {
      return Todo.fromMap(maps.first);
    }
    return null;
  }
  Future delete(int id) async {
    return await db.delete(tableTodo, where: '$columnId = ?', whereArgs: [id]);
  }
  Future update(Todo todo) async {
    return await db.update(tableTodo, todo.toMap(),
        where: '$columnId = ?', whereArgs: [todo.id]);
  }
  Future close() async => db.close();
}

さて私も教科書どおりに進めましたが・・・なぜかうまくいきませんでしたここからは
試行錯誤とGoogle先生へのお尋ね(検索)をひたすら続け
Try&Errorです

で結果的にうまく言ったのは以下のようなパターンでした。

class TestProvider {
  TestProvider._();
  
  static final TestProvider db = TestProvider._();
  static Database _database;
  Future get database async {
    if (_database != null)
      return _database;
    _database = await initDB();
    return _database;
  }
  initDB() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, "test.db");
    return await openDatabase(path, version: 1, onOpen: (db) {},
      onCreate: (Database db, int version) async {
        await db.execute("""
        CREATE TABLE test(
            id TEXT,
            comment TEXT
          )
        """);
    });
  }
  
  Future newDataInsert(Test t) async {
    final db = await database;
    var res = await db.rawQuery("select * from test where uid = ? ", [t.getId()]);
    var result;
    if (res.length == 0) {
      result = await db.rawInsert(
        "INSERT INTO test (id, comment) VALUES (?, ?)",
        [t.getId(), t.getComment()]
      );
    }
    
    return result;
  }
}

ある意味自分が忘れてしまわないようにするためのメモでございます・・・

利用する場合

Test t  = new Test();
var result = TestProvider .db.newDataInsert(t);
のようにします。
もちろん
Test t  = new Test();
TestProvider .db.newDataInsert(t).then((var result) {
//////
});

でもよろしいかと。

当初作り始めたとき・・・そこまで引っかかることもなく
なんとか作れていたFlutterでのアプリ開発の最初の難関でありました。

今思えば呼び出し方やらなんやらが問題でサンプルはちゃんと動くようにも思います・・・
まあ・・・それはそれと言うことでひとつ・・・

2019-10-25 08:51:53

Writer:ゆたさん

HomePagehome Twitter Facebook
「FlutterとDB(SQLite)の小話。」をシェアしませんか?

最新ページ

  • UserAgent(ユーザエージェント)が無くなるかもしれない問題

    セキュリティや個人情報保護昨今、セキュリティや個人情報の保護の観点ヨーロッパ、EU諸国の「一般データ保護規則(GDPR)」などなど個人情報はなるべく流してくれる...
  • Nagareが商標登録されました

    Nagare「Nagare」は、株式会社イノセントグランドの商標または、登録商標になりました。どうぞ今後とも引き続きよろしくお願いいたします!以下は特許庁のペー...
  • 機能の整理整頓の状況

    以下の機能が削除されました。Group機能記名式でのユーザのやりとりを促進するために作成されましたGroup機能でしたが利用頻度とメンテナンスのコストが割に合わ...
  • 機能の整理整頓

    機能の整理整頓を実施しようと思います。実はNagareにはすでに色々な機能があります。waterfallNagareのメイン機能です。もちろん維持されます!これ...
  • 可能性の獣(AIとか)

    NTDではないですNTD(ニュータイプデストロイ)ではないです。AIの件です。AIを使ってみたい実はAIは、すでに身近にあって使っているのかもしれません・・・い...