こんな方におすすめの記事です。
- 端末にデータ保存できるSharedPreferencesの使い方はある程度理解している
- List形式のデータを保存したい
SharedPreferencesはList形式のデータを保存したい場合、String型しか保存できません。
あらゆる型を持つListデータを保存したい場合は、ひと手間必要です。
解決策:json形式を活用
json形式のエンコードとデコードを行うことで実現できます。
僕のアプリ製作実践例よりお伝えします。
Providerの使い方はこちら。
(下準備)Map関連処理を作成
下記のClockModelは、
- Map型への変換 ※保存の際に使用
- Mapオブジェクトを代入する処理 ※読み出しの際に使用
のための下準備です。
後で使用します。
class ClockModel {
final String id;
String clock;
int currentSeconds;
int plusSeconds;
bool isMyTurn = false;
Timer timer;
ClockModel(
{this.id,
this.clock,
this.currentSeconds,
this.plusSeconds,
this.isMyTurn,
this.timer});
/// Map型に変換
Map toJson() => {
'id': id,
'clock': clock,
'currentSeconds': currentSeconds,
'plusSeconds': plusSeconds,
'isMyTurn': isMyTurn,
'timer': timer,
};
/// JSONオブジェクトを代入
ClockModel.fromJson(Map json)
: id = json['id'],
clock = json['clock'],
currentSeconds = json['currentSeconds'],
plusSeconds = json['plusSeconds'],
isMyTurn = json['isMyTurn'],
timer = json['timer'];
}
SharedPreferences Listデータ保存方法
- Map形式に変換
- Json形式に変換(エンコード)
- String型のリストに変換
- setStringListで保存
図で表すとご覧のとおり(正確ではないです)。
※アイコンは、自ブログ( https://koaramarch.com )で使用しているコアラです。
今回は、ClockModelに定義したデータをリスト化した、settingClocksというオブジェクトが保存したいデータです。
class ClockProvider with ChangeNotifier {
// 今回保存したいリスト
List<ClockModel> settingClocks = [];
ClockProvider() {
syncDataWithProvider();
}
void initSettingClocks() {
settingClocks = [
ClockModel(
id: '1',
clock: '00:05:00',
currentSeconds: 300,
plusSeconds: 5,
isMyTurn: false),
ClockModel(
id: '2',
clock: '00:05:00',
currentSeconds: 300,
plusSeconds: 5,
isMyTurn: false),
];
}
void setInitialSharedPrefrences() {
// 設定初期化
initSettingClocks();
// sharedPreferencesに保存
updateSharedPrefrences();
}
/// SharedPrefrences保存
Future updateSharedPrefrences() async {
// ①Map型変換→②Json形式にエンコード→③リスト化
List<String> myClocks =
settingClocks.map((f) => json.encode(f.toJson())).toList();
SharedPreferences prefs = await SharedPreferences.getInstance();
// ④保存
await prefs.setStringList('settingClocks', myClocks);
print('updateSharedPrefrences: $myClocks');
}
}
asyncで非同期処理化して、SharedPreferencesの処理自体はawaitにして待たせることをお忘れなく。
以下は参考までに、settingClocksへの設定とupdateSharedPrefrences()の呼び出し箇所のコードです。
ボタンタップ時の処理で設定および保存しています。
class SettingsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
Navigator.pop(context, '戻った');
return Future.value(false);
},
child: Scaffold(
appBar: AppBar(
title: Text('設定'),
actions: [
FlatButton(
child: Icon(Icons.refresh),
onPressed: () {
Provider.of<ClockProvider>(context, listen: false)
.setInitialSharedPrefrences();
},
),
],
),
body: SettingsPageHome(),
),
);
}
}
void initSettingClocks() {
settingClocks = [
ClockModel(
id: '1',
clock: '00:05:00',
currentSeconds: 300,
plusSeconds: 5,
isMyTurn: false),
ClockModel(
id: '2',
clock: '00:05:00',
currentSeconds: 300,
plusSeconds: 5,
isMyTurn: false),
];
}
void setInitialSharedPrefrences() {
// 設定初期化
initSettingClocks();
// sharedPreferencesに保存
updateSharedPrefrences();
}
SharedPreferences Listデータ読み出し方法
- getStringListで読み出し
- Jsonデコード
- MapオブジェクトをClockModelに代入
- リストに変換
保存処理の逆からたどる感じですね。
コードは以下のとおり。
/// SharedPrefrences読み出し
Future syncDataWithProvider() async {
print('syncDataWithProvider');
SharedPreferences prefs = await SharedPreferences.getInstance();
// ①読み出し
var result = prefs.getStringList('settingClocks');
print('result:$result');
// 読み出し確認
if (result != null) {
// ②デコード→③MapオブジェクトをClockModelに代入→④リストに変換
settingClocks =
result.map((f) => ClockModel.fromJson(json.decode(f))).toList();
} else {
// 必要に応じて初期化
}
}
以下は参考までに、読み出し処理の実行箇所です。
ClockProviderのコンストラクタにて読み出しています。
class ClockProvider with ChangeNotifier {
List<ClockModel> settingClocks = [];
ClockProvider() {
syncDataWithProvider();
}
}
SharedPreferencesでリストを保存する際にお役に立ちますと幸いです。
参考