Не удалось преобразовать объект в кодируемый объект: экземпляр «ThemeData»

#list #flutter #themes #sharedpreferences

Вопрос:

В моем приложении я хотел бы сохранить список , содержащий ThemeData bool и строковую переменную. Я пытаюсь сопоставить класс , чтобы сохранить его 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;
 

Я расскажу немного подробнее в своем основном ответе. В каком случае вы должны преобразовать CustomThemeModel имеющиеся у вас данные в карту? Чтобы все было просто и чтобы помочь вам решить вашу проблему, я бы предложил сначала разделить вещи логическим способом.

Я предполагаю, что вы хотите иметь список пользовательских тем, поэтому составьте список именно так. Ниже приведен краткий макет, который позволяет вам добавлять в список простым способом и создавать свой список пользовательских тем.

 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);
}
 

И затем вы можете использовать этот индекс для предоставления правильного индекса вашему пакету.

Комментарии:

1. Это сработало, но теперь, если я хочу использовать сохраненные данные с помощью fromMap, я получаю такую ошибку: Необработанное исключение: тип ‘String’ не является подтипом типа ‘ThemeData’ в приведении типа

2. С вашим методом что-то не совсем в порядке saveData . Вы преобразуете свои темы в список строк, но обрабатываете строку как объект json. Таким образом, преобразование пары ключ-значение String: ThemeData в просто необработанную строку (или ключевое значение String: Строка). Почему бы не сделать свой список пользовательских тем просто списком<CustomThemeModel>, помещая каждую новую созданную вами тему в конец списка?

3. @KrekZsole Ознакомьтесь с моим редактированием оригинального поста, возможно, это поможет вам вернуться к основам. Использование карт и преобразование в json здесь кажется совершенно ненужным.

4. Вся моя идея заключается в том, что у меня есть класс CustomThemeList, в котором я могу указать данные темы, название темы и указать, доступна ли она только для чтения или нет. Из этого класса я передаю данные тем в список<ThemeData>, потому что плагину, который я использую, нужен список тем для получения тем (плагин stacked_themes). Поэтому в основном я использую класс CustomThemeData только для отображения имени темы и использую список тем для установки темы. Вся эта концепция работает. до тех пор, пока я не захочу их спасти.

5. Я думаю, вам следует поискать решение, в котором вы откажетесь от решения JSON / map, которое у вас было (оно значительно усложняет проблему), и просто сохраните два списка в своем глобальном состоянии. Один из них содержит тематические данные для вашего пакета, а другой содержит пользовательскую модель, которая поможет вам выбрать правильный.