🔁

【Flutter】Shared_PreferencesでListを含んでいるインスタンスを保存

2024/05/31に公開

背景

アラームアプリを作成したのですが、List<〇〇>の変数を保存する必要がありました。
そういった変数をShared_Preferencesで保存する筆者のやり方をここで紹介します。

保存・取得の手順

複雑なデータ(ListやMap)を保存・取得するためには
データをShared_Preferencesで保存できる状態に変換する。
そして取得してきたデータをアプリで使える状態に再変換する。
といった処理が必要になります。下記が変換手順になります。

List<〇〇>を保存・取得する場合の変換手順
List<〇〇> 
↓↑
List<Map<String, dynamic>> //Map型を格納した変換
↓↑
List<String> //Json形式の文字列を格納したListに変換

取り扱うクラス

freezedを使ってAlarmStyleクラスを定義しました。
この定義内でMap型への変換、Map型からの変換を行う関数も定義します。

import 'package:freezed_annotation/freezed_annotation.dart';
part 'alarm_style.freezed.dart';

@freezed
class AlarmStyle with _$AlarmStyle {
  const AlarmStyle._();

  const factory AlarmStyle({
    required bool state,//OnOff情報
    required DateTime time,//時刻
    required List<bool> routine00,//定期的な鳴動についての情報①
    required List<bool> routine01,//定期的な鳴動についての情報②
    required List<bool> routine02,//定期的な鳴動についての情報③
  }) = _AlarmStyle;
  // Map形式に変換
  Map<String, dynamic> toJson() {
    return {
      'state': state,
      'time': time.toIso8601String(),
      'routine00': routine00,
      'routine01': routine01,
      'routine02': routine02,
    };
  }
  // Map形式からの変換
  factory AlarmStyle.fromJson(Map<String, dynamic> json) {
    return AlarmStyle(
      state: json['state'],
      time: DateTime.parse(json['time']),
      routine00: List<bool>.from(json['routine00']),
      routine01: List<bool>.from(json['routine01']),
      routine02: List<bool>.from(json['routine02']),
    );
  }
}

保存するコード

下記の1行のコードでAlarmStyleを1つずつMap型に変換し、Json形式に文字列型に変換した変数を
まとめてListにしている。

import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';

saveList(List<AlarmStyle> alarmList) async {
  final prefs = await SharedPreferences.getInstance();
//この1行で保存のための変換を行なっている。
  List<String> alarmStyleStrings =
      alarmList.map((alarmStyle) => jsonEncode(alarmStyle.toJson())).toList();
  await prefs.setStringList('alarm_list', alarmStyleStrings);
}

取得するコード

先ほどとは逆でreturnのコードでJson形式の文字列型変数を1つずつMap型に変換し、AlarmStyle型
まとめてListにしている。

Future<List<AlarmStyle>> loadList() async {
    const String keyAlarmList = 'alarm_list';
    final prefs = await SharedPreferences.getInstance();
    final List<String>? encodedList = prefs.getStringList(keyAlarmList);

     //何も保存されていない場合は7:00のアラームを生成
    if (encodedList == null) {
      return [
        AlarmStyle(
            state: false,
            time: DateTime(2000, 1, 1, 7, 0, 0, 0, 0),
            routine00: [true],
            routine01: [false, false],
            routine02: [false, false, false, false, false, false, false])
      ];
    }
    //この1行で取得のための変換を行なっている。
    return encodedList
        .map((encodedAlarm) => AlarmStyle.fromJson(jsonDecode(encodedAlarm)))
        .toList();
  }

Discussion