Flutter存储含ThemeData对象到SharedPreferences报编码错误如何解决?
问题原因
json.encode仅支持序列化Dart内置基础类型(数字、字符串、布尔、列表、键为字符串且值为可序列化类型的Map),你直接把ThemeData实例放入Map中序列化时,Json序列化器无法识别自定义的ThemeData类,就会抛出转换失败的错误。
解决方案
不要直接存储ThemeData实例,仅存储你自定义修改过的ThemeData的属性值,反序列化时再用这些属性重新构造ThemeData实例即可。
修改后的CustomThemeModel参考代码如下:
class CustomThemeModel { ThemeData myThemeData; String themeName; bool readOnly = false; CustomThemeModel({ required this.myThemeData, required this.themeName, required this.readOnly, }); // 反序列化:从存储的Map还原实例 CustomThemeModel.fromMap(Map map) : themeName = map['themeName'], readOnly = map['readOnly'], // 用存储的属性重新构造ThemeData,可根据你的实际自定义属性增删字段 myThemeData = ThemeData( brightness: Brightness.values[map['themeBrightnessIndex']], primaryColor: Color(map['primaryColorValue']), // 你自定义修改过的其他ThemeData属性都可以在此处补充还原 ); // 序列化:仅把需要的ThemeData属性转成基础类型存入Map Map<String, dynamic> toMap(){ return{ // 只存你修改过的ThemeData属性,转成可序列化的基础类型 'themeBrightnessIndex': myThemeData.brightness.index, 'primaryColorValue': myThemeData.primaryColor.value, // 你自定义的其他ThemeData属性在此处补充存储 'themeName': themeName, 'readOnly': readOnly, }; } }
修改完成后原有的saveData方法就可以正常执行,序列化后的字符串列表可以直接存入SharedPreferences。
注意事项
- 不需要存储
ThemeData的所有属性,仅需要存储你主动修改过的配置,未修改的属性使用ThemeData默认值即可,可以大幅减少存储的冗余数据 - 所有
Color类型都可以通过.value属性转为int类型存储,读取时传入Color(存储的int值)即可还原颜色 - 枚举类型可以通过
.index存储为int,读取时用枚举类.values[存储的int值]还原枚举
内容的提问来源于stack exchange,提问作者KrekZsole
相关产品推荐
相关产品推荐

