使用SharedPreferences实现Flutter地铁站点收藏持久化遇错求助
问题分析与解决方案
核心问题拆解
- 枚举类型无法直接JSON序列化:
BranchType是枚举,默认jsonEncode无法处理枚举值,会触发序列化错误。 - 自定义类
TransitData缺少JSON转换逻辑:如果TransitData是自定义类,未实现toJson/fromJson方法会导致序列化失败。 - SharedPref方法逻辑错误:返回类型与实际数据结构不匹配,且空值处理不当会引发JSON解析异常。
- 异步调用时机错误:在
setState中直接调用异步存储方法,未等待写入完成就读取,可能导致数据不一致。
逐步修复代码
1. 修复枚举的JSON序列化
给BranchType扩展序列化/反序列化方法:
enum BranchType { red, blue, green } extension BranchTypeExtension on BranchType { String toJson() => name; // 用枚举名称作为序列化值 static BranchType fromJson(String json) => BranchType.values.firstWhere((e) => e.name == json); }
2. 完善MetroStation的JSON转换逻辑
更新fromJson和toJson,适配枚举和TransitData:
class MetroStation { final String ukrName; final String engName; final double depth; final String iconImage; final TransitData? transitData; final BranchType branchType; bool isFavourite; MetroStation({ required this.isFavourite, required this.branchType, this.transitData, required this.depth, required this.iconImage, required this.ukrName, required this.engName, }); factory MetroStation.fromJson(Map<String, dynamic> json) => MetroStation( ukrName: json['ukrName'], engName: json['engName'], depth: json['depth'], iconImage: json['iconImage'], branchType: BranchTypeExtension.fromJson(json['branchType']), isFavourite: json['isFavourite'], transitData: json['transitData'] != null ? TransitData.fromJson(json['transitData']) : null, ); Map<String, dynamic> toJson() => { 'ukrName': ukrName, 'engName': engName, 'depth': depth, 'iconImage': iconImage, 'branchType': branchType.toJson(), 'isFavourite': isFavourite, 'transitData': transitData?.toJson(), }; // 重写==和hashCode,确保remove方法能正确匹配元素 @override bool operator ==(Object other) => identical(this, other) || other is MetroStation && runtimeType == other.runtimeType && ukrName == other.ukrName && engName == other.engName; @override int get hashCode => ukrName.hashCode ^ engName.hashCode; }
3. 实现TransitData的JSON转换
假设TransitData结构如下,补充转换方法:
class TransitData { final String someField; TransitData({required this.someField}); factory TransitData.fromJson(Map<String, dynamic> json) => TransitData( someField: json['someField'], ); Map<String, dynamic> toJson() => { 'someField': someField, }; }
4. 重构SharedPref类
适配列表类型,修复空值处理:
const favouriteKey = 'favourite_stations'; class SharedPref { static Future<void> saveFavourites(List<MetroStation> stations) async { final prefs = await SharedPreferences.getInstance(); final jsonList = stations.map((station) => station.toJson()).toList(); await prefs.setString(favouriteKey, jsonEncode(jsonList)); } static Future<List<MetroStation>> getFavourites() async { final prefs = await SharedPreferences.getInstance(); final jsonString = prefs.getString(favouriteKey); if (jsonString == null) return []; final jsonList = jsonDecode(jsonString) as List<dynamic>; return jsonList.map((json) => MetroStation.fromJson(json as Map<String, dynamic>)).toList(); } }
5. 修正UI中的异步调用逻辑
确保先完成存储再读取数据:
setState(() { if (station.isFavourite) { favouriteData.remove(station); station.isFavourite = false; } else { favouriteData.add(station); station.isFavourite = true; } // 调试打印 debugPrint('-----------'); for (var element in favouriteData) { debugPrint(element.ukrName); } debugPrint('-----------'); }); // 等待存储完成后再读取 await SharedPref.saveFavourites(favouriteData); final savedFavourites = await SharedPref.getFavourites(); print(savedFavourites.map((s) => s.ukrName).toList());
内容的提问来源于stack exchange,提问作者Gamma514
相关产品推荐
相关产品推荐

