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)の小話。」をシェアしませんか?

最新ページ

  • プログラマーの美徳

    プログラマーには三大美徳があります。この三大美徳を言い始めたのは、「Larry Wall」氏でございます。Perlの生みの親としても大変有名人ですね。美徳・・・...
  • User-AgentがなくなるのでUser-Agent Client Hints(UA-CH)がやってくる話

    ユーザーエージェントが無くなるかもしれない・・・が来年になりそうですが、実際にやってくる感じをひしひしと感じています。前回のエージェントが無くなる件について・・...
  • ThinkPad トラックポイント キーボード II

    6月はじめに予約してたんですがようやく届きました。先週の金曜日ぐらいに。有線に比べて重い(当たり前)以前の有線のものをずっと使ってました。ずっと使っていたと言い...
  • 今後のNagareに追加しようとしていることなど・・・

    まずはゲームです現在開発中のゲームを兎にも角にも完成させなければなりません。今現在の進捗ですと予定していた7月のベータテストはいつの間にか アルファテスト1 ぐ...
  • FF7Rを初めてFF7オリジナルをやりたくなるなど。

    FF7Rの次はまだか次はまだですかね?オリジナルを少し遊んでみたくなりました。なつかしい。で自分的に色々忘れている(忘らるる都)なので、ここにメモがてらやること...