Flutter iOS 音声メモアプリ開発(Tips) localstore
こちらの記事で端末内にデータを保存するlocalstoreパッケージの基本的な使い方について記述しました。
Flutterのlocalstoreパッケージの動作について、もう少し詳しくみていきます。
データファイル
localstoreのデータの実態は、JSONファイルです。このファイルの中身の確認方法について調べてみました。
以下は、こちらの記事を参考にさせていただきました。 https://capibara1969.com/2836/
iOSアプリのフォルダ構成
最初にvoice_memoアプリでデータを登録しておきます。
この状態で端末をMacに接続し、Xcodeからvoice_memoアプリのファイルをダウンロードします。
XcodeのメニューからWindows>Devices and Simulators を選択して、以下の画面を表示させます。
Download Containerを選択すると、以下のAppDataがダウンロードされます。
iOSの場合、アプリケーション毎に、独自のフォルダが割り当てられるようですが、今回の場合、Documents ,Library ,SystemData ,tmpフォルダが作成されていました。
アプリで記録したユーザデータの類は、Documents以下に保存するようです。
先述のように、2つのメモを登録した状態で、ファイルをダウンロードすると、AppData/Documents/todo以下に2つのファイルができていました。
ファイルの中身は以下の通りです。
{"id":"2023-02-05 16:54:15.415980","title":"今日も1日がんばりました","time":1675583655415,"sentiment":"😀","done":false}
{"id":"2023-02-05 17:18:41.033995","title":"明日も良い1日でありますように","time":1675585121033,"sentiment":"😀","done":false}
localstoreのデータはitemごとに一つのファイルが作成されていることがわかりました。
ファイル名がTimeスタンプになっているのは、後述する理由でidをTimeスタンプにしているためです。標準的な使い方だと、ファイル名はランダムにセットされたidになります。
データの表示順
localstoreで保存したデータをListViewで表示する際に、順番が入れ替わることがありました。そこで、initState()内で_itemsをソートする一文を追加しました。
void initState() {
_subscription = _db.collection('todos').stream.listen((event) {
setState(() {
final item = Todo.fromMap(event);
_items.putIfAbsent(item.id, () => item);
_items = SplayTreeMap.from(_items, (a, b) => a.compareTo(b)); // <- 追加
});
});
if (kIsWeb) _db.collection('todos').stream.asBroadcastStream();
super.initState();
}
この場合、SplayTreeMapはidでソートすることとなります。登録した順にデータを並べたかったので、idをTimeスタンプに変更することで、時間順にソートすることとしました。
//final id = Localstore.instance.collection('todos').doc().id; // 基本的な使い方
final id = now.toString(); // 今回の処理
この方法はあまり良い方法ではないかもしれません。もっと良い方法をご存知の方がおられましたら、TwitterのDMかメールでご教示いただけますと助かります。
ちなみに、localstoreのidの生成は、以下のような処理になっていました。
@override
DocumentRef doc([String? id]) {
id ??= int.parse(
'${Random().nextInt(1000000000)}${Random().nextInt(1000000000)}')
.toRadixString(35)
.substring(0, 9);
return DocumentRef(id, this);
}