Flutter側からスマートフォン本体のローカルストレージにデータを保存する方法は何通りかあります。メジャーなやり方は下記のパターンに分類されます。
- ファイル自体の読み取りと書き込み
- SQLiteを利用する
- SQLCipherを利用する
- SharedPreferencesを利用する
- Localstoreを利用する
ファイルを読み書きさせる
他の方法と同様にこの手法もpath_providerというプラグインを使います。path_providerとdart:ioライブラリを併用して、ローカルにファイルを書き込んだり、参照したりする方法です。
(参考:https://docs.flutter.dev/cookbook/persistence/reading-writing-files)
path_providerのインストールの仕方はhttps://pub.dev/packages/path_provider/installに記載されているので参考にしてみてください。
大まかな流れは
- ローカルパスを特定(検知)する
- ファイルパスを参照する
- ファイルの読み書き
となります。Flutter公式ドキュメントのサンプルコードをファイル操作の部分だけ抜き出すと、
import 'dart:async';
import 'dart:io';
// 省略
import 'package:path_provider/path_provider.dart';
// 省略
class CounterStorage {
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/counter.txt');
}
Future<int> readCounter() async {
try {
final file = await _localFile;
// Read the file
final contents = await file.readAsString();
return int.parse(contents);
} catch (e) {
// If encountering an error, return 0
return 0;
}
}
Future<File> writeCounter(int counter) async {
final file = await _localFile;
// Write the file
return file.writeAsString('$counter');
}
}
// 以下省略
というような記述方法になります。そんなに難しいことはしていないですね。
ファイルの保存などは、オフラインで文章を読めるようなアプリに活躍しそうです。単純にキーと値だけを保存したい場合には向いていない(ちょっと大がかりすぎるかな)という印象です。
SQLiteを利用する
アプリ制作者には馴染みが深めなSQLiteも使用できます。React Nativeでも使えますね。アプリ開発の現場では一番ポピュラーな方法かもしれません。
SQLiteを利用するためにはsqfliteというパッケージが必要です。インストールは
flutter pub add sqflite
で行います。
もちろんSQLiteですのでDBにCRUD(Create, Read, Update, Delete)して、ローカルへデータを格納したり取り出したり出来ます。
ただ、注意すべきなのはSQLiteはデバイス(実機)で動作するため、テスト環境でテストすることができません。そこで、sqflite_common_ffiというパッケージをテスト段階で使用します。ffiというのは(おそらく)Foreign Function Interfaceの略で実機とは別のデバイス(プラットフォーム)で動くことを目的として作られたパッケージを意味します。
sqflite_common_ffiのインストール方法はhttps://pub.dev/packages/sqflite_common_ffi/installに書かれていますのでそちらを見ながら試してみて下さい。
SQLCipherを利用する
iphoneやipadのアプリのデータベースは、暗号化をした方が良いとされています。対策しないと中身が見られてしまうことがあるためです。それを防止するためにSQLCipherが使われることがあります。ただ、ライセンスに注意する必要があります。
SQLCipherはBSDライセンスで商用でも無料で利用出来ますが、念のためSQLCipherのライセンスを確認してください。(BSDライセンスについてちょっと自信無いのでご自身で判断してください……)
SQLCipher Commercial Editionというのもあり、こちらは有料でサポートを受けられるというものです。ご自身で完結できる場合はSQLCipher Community Editionで無料で使えるはずです。(間違っていましたらご連絡いただけると助かります!)
SharedPreferencesを利用する
SharedPreferencesは比較的単純なデータ構造にしか対応できないため、アプリケーションの設定などに用いられることが多いパッケージです。
Key(キー)と対になるValue(バリュー)を端末内に保持します。
利用出来る型は、
- String
- int
- float
- long
- boolean
に限られますので、そこまで汎用性の高いパッケージではありません。Valueにオブジェクトを入れたい場合などは別の方法を利用することをおすすめします。ちなみに保存したデータはXML形式で読み書きされます。
Localstoreを利用する
LocalStoreはJSONベースのストレージパッケージです。NoSQLを採用しているため、扱いが簡素で比較的馴染みやすいと思います。
利用方法は公式ページを見ると、まずmain()の中でWidgetsFlutterBinding.ensureInitialized();を呼び出して初期化させます。(※importについては後述)
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
関連パッケージをimportしないと使えないので、importします。
import 'package:flutter/material.dart';
import 'package:localstore/localstore.dart';
使いたい場所でインスタンスを作成。
final db = Localstore.instance;
初期起動の際は、データを作成。db.collection('todos').doc(id).set()
でデータをセット出来ます。
※アプリを開いた度に毎回↓の処理をしちゃうと毎回初期化されますので注意……
// gets new id
final id = db.collection('todos').doc().id;
// save the item
db.collection('todos').doc(id).set({
'title': 'Todo title',
'done': false
});
データの取り出し方は
final data = await db.collection('todos').doc(id).get();
と、いたってシンプルですね。
全体像のサンプルはhttps://pub.dev/packages/localstore/exampleにありますので確認してみてください。
まとめ
Flutterにもいろいろなローカルデータの入出力方法がありますね。
複雑なデータの処理が必要ならSQLiteを使って、単純なデータ構造であればJSONベースやXMLベースの方法が良いと思います。是非チャレンジしてみてください。