Flutter: バックアップした「hive」のファイルをインポート(リストア)して上書きしても、データが更新されない
結論:「hive」のファイルを上書きする前に、boxをcloseする
2022/5/3 Flutter エラー・バグ日記
ローカルデータベース(DB)に「hive」を使用し、端末内に作成される「.hive」と「.lock」ファイルのバックアップ機能を実装した。
しかし、バックアップしたファイルを、外部からインポート(リストア)して「.hive」と「.lock」ファイルを上書き保存しても、画面表示されるデータが、インポート前(リストア前)のままで、更新されなかった。
実装方法の概略(問題解消前)は、以下のとおり。
- 「path_provider」パッケージを利用し、「getApplicationDocumentsDirectory()」メソッドで、端末内のアプリ専用フォルダのDirectory型インスタンスを作成
- 同フォルダ内にある「hive」のDBファイル(「####.hive」と「####.lock」。「sqflite」を使った場合の「####.db」に相当するファイル)のファイル名を使って「join(上記Directory型インスタンス.path, 上記ファイル名)」により、フルパス名を作成
- 「File(フルパス名)」にて、インポート(リストア)先のFile型のインスタンスを作成
- バックアップ先から読込んだバックアップファイルのデータを使って、「上記File型インスタンス.writeAsBytes(バックアップファイルのList<int>型)」メソッドで上書き保存
再描画を行う状態管理には「riverpod」を使用しており、インポート(リストア)後のDBから、描画用の変数に値を読込んだ上で、「StateNotifier」を通じて、変更通知を行っている。
過去に、ローカルDBとして「sqflite」を採用したアプリでは、この方法でうまく行ったのだが。。。
試しにアプリを再起動してみると、今度は、インポート(リストア)後のデータに画面表示が更新されていた。
従って、端末内のDBファイル自体は、きちんと更新されている。
「hive」の公式ドキュメントを改めてチェックするも、バックアップ・インポート(リストア)方法の情報は載っていない。
仕方なくググってみると、まさに同じ質問に対して「hive」作者の方が回答されているイシューがあった。
これによると、「hive」のファイルを上書きする前に、boxをcloseする必要がある模様。
そこで、以下のようにプロセスを修正したら、無事、インポート(リストア)後のデータが画面表示されるようになった(問題解消!)。
<問題解消時の実装方法>
- 「path_provider」パッケージを利用し、「getApplicationDocumentsDirectory()」メソッドで、端末内のアプリ専用フォルダのDirectory型インスタンスを作成
- 同フォルダ内にあるhiveのDBファイル(「####.hive」と「####.lock」。「sqflite」を使った場合の「####.db」に相当するファイル)のファイル名を使って「join(上記Directory型インスタンス.path, 上記ファイル名)」により、フルパス名を作成
- 「File(フルパス名)」にて、インポート(リストア)先のFile型のインスタンスを作成
- 【追加】「await boxのインスタンス.close()」メソッドにより、開いていたbox(DBファイル)を閉じる
- バックアップ先から読込んだバックアップファイルを使って、「上記File型インスタンス.writeAsBytes(バックアップファイルのList<int>型)」メソッドで上書き保存
- 【追加】「boxのインスタンス = await Hive.openBox(box名)」により、再びboxを開き、boxのインスタンスを再作成
なお、改めて「hive」のQ&Aを見てみると、
ボックスが不要になった場合は、ボックスを閉じる必要があります。キャッシュされたすべてのキーとボックスの値はメモリから削除され、アクティブな読み取りおよび書き込み操作がすべて終了すると、ボックスファイルが閉じられます。
https://docs.hivedb.dev/#/basics/boxes?id=close-box
という趣旨の記述があった。
「hive」は、DBからデータを読込むとき(「get」メソッド実行時)、非同期処理にする必要がなく、瞬時にデータ取得できる点が便利なのだが、恐らくメモリやキャッシュにデータを保存しているからなのだろう。
ただ、この影響で、boxをきちんと閉じないと、DBのファイル自体が上書きされても、メモリやキャッシュのデータが更新されず、再描画しても表示が更新されない、、という結果になったのでは?というのが自分なりの考察(違っているかも知れませんが、、、)。
リリースしたアプリ(全てFlutterで開発)
個人アプリ開発で役立ったもの
おすすめの学習教材
\超初心者向けでオススメな元Udemyの講座/
\キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/
\Gitの基礎について無料で学べる/
おすすめの学習書籍
\実用的。image_pickerに関してかなり助けられた/
\Dartの基礎文法を素早くインプットできる/