[Flutter]ネイティブアプリで保存した値を取得するためには？？

![スクリーンショット 2023-07-10 10.25.29（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/8e71c4d9-0093-16c3-605f-b94d667919d3.png)



こんにちわ。

今回はFlutterを勉強している中で<b>「え！知らなかった！？！？」　</b>ということがありましたので共有したいと思います。

ちょっとしたデータをローカルに保存したい場合は、Shared PreferencesというFlutter公式のプラグインを使用することで簡単に実現できます。例えばアプリに関する設定情報などのデータを保存したい場合に便利です！

そんな便利な`Shared Preferences`ですが、落とし穴があったので書いていこうと思います！！

# プロフィール

![スクリーンショット 2023-06-13 7.33.21（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/5a9bcf72-ccbf-7eb3-a6b6-22d45dd09200.png)



# shared_preferencesとは

https://pub.dev/packages/shared_preferences


　shared_preferencesでは、Flutterで作成したアプリ内で、データを保存したり読み出したりできます。

　データは非同期でディスクに保存される可能性があり、書き込みが戻った後にディスクに保存されるという保証はないため、このプラグインは重要なデータの保存には適さないそうです。


<b>こんな場面で使用されることが多いです。</b>
- テーマのダークモードやライトモード
- 言語設定
- 状態の保存


:::note info
##### iOSエンジニアの方にもわかりやすく説明すると

- iOSでいうと<b>UserDefaults</b>にあたる。
- データの保存場所としては`/AppData/Library/Preferences/`に格納されるらしいです。
    
 （間違っていたら教えてください😀）
:::


:::note info
##### Androidエンジニアの方にもわかりやすく説明すると

- Androidで言うと<b>SharedPreferences</b>にあたる。
- データの保存場所としては`/data/data/<your app package name>/shared_prefs/`に格納されるらしいです。
    
 （間違っていたら教えてください😀）
:::


# shared_preferencesではダメなのか

##### 結論から言います。ダメではないのですが、場合によっては、保存/取得ができないトラブルがあります。

##### その場合の例として、ネイティブアプリ（iOS/Android）をリプレイスするときに、保存していたローカルデータは取得することができません。


![bikkuri_me_tobideru_man.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/76201622-c8e8-bb70-652d-05091fdef662.png)


その理由としては、shared_preferencesでは保存・取得の際に<b>`flutter.`</b>というプレフィックス（その単語なり何なりの前（頭）にくっつく文字のこと）をキーに付与してデータを扱っているからです。

例えば、

```dart
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);
  }
```

:::note info

このコードでは取得（get）・保存（set）をしているコードです。
ここでは、`_key`は、`preference`にしていますが、実際には、<b>`flutter.preference`</b>というキーで値を取得・保存しています。

flutterのみでは問題はありませんが、ネイティブで保存された値のキーは、プレフィックス(`flutter.`)なしで保存されているため、`shared_preferences`で取得しようとすると、取得ができません。


:::



shared_preferenceの中身を見てみると。。。

https://github.com/flutter/plugins/blob/e014c208909772cee2328a91b7225e667a2681a9/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart



```dart:一部抜粋
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);
```


<b>Flutter・・・`flutter.preference`</b>

<b>ネイティブ・・・`preference`</b>

となり、うまく取得できない問題があります。
このような問題は、ネイティブ→Flutterでのリプレイスなどで起こる問題なので普段はあまりないとは思うので、なかなか調べられている記事が少なかったです。(^^;;


# 解決策

#### 色々あると思いますが、[native_shared_preferences](https://pub.dev/packages/native_shared_preferences)のパッケージを使用した方が良さそうです。

#### native_shared_preferencesを使うことで、ネイティブからプレフィックスなしで値を取って来れます。

https://pub.dev/packages/native_shared_preferences



### ただ、注意点として

- 以前のネイティブアプリバージョンからの取得のみに使用の方が良さそう。
- 移行の管理をする場合には、[version_migration](https://pub.dev/packages/version_migration)を使用した方が良さそう。
- 実際にマイグレーションする際には正確に値が移行できているかテストした方がいい。


# 最後に
このようなトラブルは多くはないのですが、一つの知識として知っておくといいと思います！





<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/bdcb72a8-4215-0d2c-0088-60bb9b73c50e.png">



<b>ps：7月8日に親友とディズニーランドに行きました！４０周年のパレードを初めてみれてとても幸せでした。さらに最近はキャラクターとハグが解禁されて、推しのファンタジアミッキーとハグができてハッピーでした😀



<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/8b0d2e34-7295-ceca-b8bd-9411116e56b8.jpeg">










# 参考文献

https://techracho.bpsinc.jp/wingdoor/2020_12_08/100966

https://tech.amefure.com/swift-userdefaults#:~:text=UserDefaults%E3%81%8C%E3%81%A9%E3%81%93%E3%81%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92,%2FLibrary%2FPreferences%2F%20%E3%81%A7%E3%81%99%E3%80%82