こんにちわ。
今回はFlutterを勉強している中で「え!知らなかった!?!?」 ということがありましたので共有したいと思います。
ちょっとしたデータをローカルに保存したい場合は、Shared PreferencesというFlutter公式のプラグインを使用することで簡単に実現できます。例えばアプリに関する設定情報などのデータを保存したい場合に便利です!
そんな便利なShared Preferences
ですが、落とし穴があったので書いていこうと思います!!
プロフィール
shared_preferencesとは
shared_preferencesでは、Flutterで作成したアプリ内で、データを保存したり読み出したりできます。
データは非同期でディスクに保存される可能性があり、書き込みが戻った後にディスクに保存されるという保証はないため、このプラグインは重要なデータの保存には適さないそうです。
こんな場面で使用されることが多いです。
- テーマのダークモードやライトモード
- 言語設定
- 状態の保存
shared_preferencesではダメなのか
結論から言います。ダメではないのですが、場合によっては、保存/取得ができないトラブルがあります。
その場合の例として、ネイティブアプリ(iOS/Android)をリプレイスするときに、保存していたローカルデータは取得することができません。
その理由としては、shared_preferencesでは保存・取得の際にflutter.
というプレフィックス(その単語なり何なりの前(頭)にくっつく文字のこと)をキーに付与してデータを扱っているからです。
例えば、
class Preference {
static const _key = 'preference';
Future<bool> get() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool(_key) ?? false;
}
Future<bool> set() async {
final prefs = await SharedPreferences.getInstance();
return prefs.setBool(_key, true);
}
このコードでは取得(get)・保存(set)をしているコードです。
ここでは、_key
は、preference
にしていますが、実際には、flutter.preference
というキーで値を取得・保存しています。
flutterのみでは問題はありませんが、ネイティブで保存された値のキーは、プレフィックス(flutter.
)なしで保存されているため、shared_preferences
で取得しようとすると、取得ができません。
shared_preferenceの中身を見てみると。。。
static const String _prefix = 'flutter.';
Future<bool> _setValue(String valueType, String key, Object value) {
final String prefixedKey = '$_prefix$key';
if (value == null) {
_preferenceCache.remove(key);
return _store.remove(prefixedKey);
} else {
if (value is List<String>) {
_preferenceCache[key] = value.toList();
} else {
_preferenceCache[key] = value;
}
return _store.setValue(valueType, prefixedKey, value);
}
}
Future<bool> setBool(String key, bool value) => _setValue('Bool', key, value);
Flutter・・・flutter.preference
ネイティブ・・・preference
となり、うまく取得できない問題があります。
このような問題は、ネイティブ→Flutterでのリプレイスなどで起こる問題なので普段はあまりないとは思うので、なかなか調べられている記事が少なかったです。(^^;;
解決策
色々あると思いますが、native_shared_preferencesのパッケージを使用した方が良さそうです。
native_shared_preferencesを使うことで、ネイティブからプレフィックスなしで値を取って来れます。
ただ、注意点として
- 以前のネイティブアプリバージョンからの取得のみに使用の方が良さそう。
- 移行の管理をする場合には、version_migrationを使用した方が良さそう。
- 実際にマイグレーションする際には正確に値が移行できているかテストした方がいい。
最後に
このようなトラブルは多くはないのですが、一つの知識として知っておくといいと思います!
ps:7月8日に親友とディズニーランドに行きました!40周年のパレードを初めてみれてとても幸せでした。さらに最近はキャラクターとハグが解禁されて、推しのファンタジアミッキーとハグができてハッピーでした😀
参考文献