【问题标题】:Converting object to an encodable object failed: Instance of 'ThemeData'将对象转换为可编码对象失败:“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);
  }

【问题讨论】:

    标签: list flutter themes sharedpreferences


    【解决方案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 以帮助您选择正确的。
    猜你喜欢
    • 2020-08-21
    • 2023-04-09
    • 2021-05-19
    • 1970-01-01
    • 2020-12-31
    • 2018-09-20
    • 2021-08-09
    • 2021-10-05
    • 2021-04-08
    相关资源
    最近更新 更多