将对象转换为可编码对象失败:“ThemeData”实例

Posted

技术标签:

【中文标题】将对象转换为可编码对象失败:“ThemeData”实例【英文标题】:Converting object to an encodable object failed: Instance of 'ThemeData' 【发布时间】:2021-11-04 04:41:47 【问题描述】:

在我的应用程序中,我想保存一个包含ThemeData、一个布尔值和一个字符串变量的列表。我正在尝试映射该类以将其保存到Shared Preferences,但在对列表进行编码时出现此错误:

Converting object to an encodable object failed: Instance of 'ThemeData'

这是 CustomThemeModel 类:

class CustomThemeModel 

  ThemeData myThemeData = new ThemeData();
  String themeName;
  bool readOnly = false;

  CustomThemeModel(
    required this.myThemeData,
    required this.themeName,
    required this.readOnly,
  );

  CustomThemeModel.fromMap(Map map) :
        this.myThemeData = map['myThemeData'],
        this.themeName = map['themeName'],
        this.readOnly = map['readOnly'];

  Map toMap()
    return
      'myThemeData': this.myThemeData,
      'themeName': this.themeName,
      'readOnly': this.readOnly,
    ;  
  

以及将保存列表的 void 方法:

void saveData()
    List<String> spList = myThemes.map((e) => json.encode(e.toMap())).toList();
    print(spList);
  

【问题讨论】:

【参考方案1】:

您可以尝试像这样强制转换您的 fromMap 构造函数。

  CustomThemeModel.fromMap(Map map) :
        this.myThemeData = map['myThemeData'] as ThemeData,
        this.themeName = map['themeName'] as String,
        this.readOnly = map['readOnly'] as bool;

我将在我的主要答案中详细说明。您必须将您拥有的CustomThemeModels 转换为地图的用例是什么?为了简单起见并帮助您解决问题,我建议您先以合乎逻辑的方式进行拆分。

我假设您想要一个自定义主题列表,因此请创建一个列表。下面是一个快速模型,可让您以基本方式添加到列表中并构建自定义主题列表。

final List<CustomThemeModel> customThemes = [];
void addToCustomThemes(CustomThemeModel model) 
  customThemes.add(model);


...

InkWell(
  onTap: () 
    addToCustomThemes(CustomThemeModel(
        myThemeData: ThemeData(),
        themeName: 'customThemeName1',
        readOnly: false,
      ),
    );
  
)

你可以很容易地在这个列表中找到一个主题模型。

for (final theme in customThemes) 
  return theme.where(theme.themeName == 'my theme name');

Edit2:对于您的特定用例,我会做这样的事情。请注意,代码是专门在此处的文本编辑器中键入的,因此如果不进行一些小的调整,它可能无法运行,但想法就在那里。

final List<CustomThemeModel> customThemeModels = [
  CustomThemeModel(
    myThemeData: ThemeData(),
    themeName: 'My name',
    readOnly: true,
  ),
  // Add all CustomThemeModels here
];
// Create the list of ThemeData from your custom list
final List<ThemeData> themeData = customThemeModels.map((themeModel) 
  return themeModel.myThemeData;
).toList();

现在,您的两个列表的顺序是相同的,因此您可以通过提供您提供的名称来找到要使用的主题的索引。

int getIndex(nameToCheck String) 
  return customThemeModels.indexWhere((theme) => theme.themeName == nameToCheck);

然后您可以使用此索引为您的包提供正确的索引。

【讨论】:

它工作了,但是现在如果我想将保存的数据与 fromMap 一起使用,我会收到如下错误:未处理的异常:类型“字符串”不是类型转换中“主题数据”类型的子类型 您的saveData 方法有些问题。您将主题转换为字符串列表,但您将字符串视为 json 对象。因此,将 String: ThemeData 的键值对转换为原始 String(或 String: String 的键值对)。为什么不将您的自定义主题列表设为一个 List,将您创建的每个新主题推到列表末尾? @KrekZsole 查看我对原始帖子的编辑,也许这可以帮助您回归基础。在这里使用地图和转换为 json 似乎完全没有必要。 我的整个想法是我有一个 CustomThemeList 类,我可以在其中提供 ThemeData、主题的名称以及它是否是只读的。从这个类中,我将 ThemeData 提供给 List 因为我正在使用的插件需要一个 ThemeData 列表来获取主题(插件是stacked_themes)。所以基本上我只使用 CustomThemeData 类来显示 Theme 名称,并使用 ThemeData 列表来设置 Theme。这整个概念有效。直到我想保存它们。 我认为您应该寻找一种解决方案,放弃您拥有的 JSON / map 解决方案(它使问题过于复杂),并在您的全局状态中存储两个列表。一个包含您的包的 ThemeData,另一个包含 CustomThemeModel 以帮助您选择正确的。

以上是关于将对象转换为可编码对象失败:“ThemeData”实例的主要内容,如果未能解决你的问题,请参考以下文章

Map<int, List<int>> 转换为可编码对象失败

Swift Firebase - 将估计的 ServerTimestamp 与可编码的自定义对象相结合

Swift 4 可编码领域对象子类

Alamofire:具有额外属性的可编码对象

我想将字符串值从 API 转换为自定义可编码模型 SWIFT

如何为可编码对象提供自定义代码功能