1

in my Flutter project I have a class Category witch contains a String, Icon, IconData and two Colors: (I don't want to store the icon, because I can recreate it with my iconData)

class Category {
  Icon icon;
  IconData iconData;
  Color color;
  Color backgroundcolor;
  String name;

[...]

Map<String, dynamic> toMap() {
    return {
      'iconData': iconData,
      'color': color,
      'backgroundcolor': backgroundcolor,
      'name': name
    };
  }

for my project I imported the sqflite database, created a table categories(with "CREATE TABLE categories(name TEXT, iconData BLOB, color BLOB, backgroundcolor BLOB")) and now want to insert a category into my database with the following:

Future<void> insertCategory(Category category) async {
  // get reference to the database
  final Database db = await database;

  // insert new category
  await db.insert('categories', category.toMap(),
      conflictAlgorithm: ConflictAlgorithm.replace);

  print("Category inserted.");
}

But when I try to insert a category I get an Argument Error (Invalid argument: Instance of 'IconData') and I can't figure out what's the problem.

jonryan
  • 11
  • 2
  • Blob is raw data - array of bytes (most likely). Here I don't see conversion of IconData to array of bytes. So you can extend your `toMap` to do so. Other solution is to store only `codePoint` (may be `fontFamily`) as that is all you need, and cnostruct IconData from codePoint & fontFamily when required. – Chenna Reddy Sep 23 '19 at 14:53

2 Answers2

0

you can save icon data with String type
and you need a mapping from string to your icon either Icons or FontAwesomeIcons or ...

Map<String, IconData> iconMapping = {
  'facebook' : FontAwesomeIcons.facebook,
  'twitter' : FontAwesomeIcons.twitter,
  'home' : FontAwesomeIcons.home,
  'audiotrack' : Icons.audiotrack,
};

@override
Widget build(BuildContext context) {
  return Icon(iconMapping [icon], color: HexColor(color));
}

Similar question and answer
Trying to dynamically set the Icon based on a JSON string value
Flutter: Show different icons based on value

chunhunghan
  • 51,087
  • 5
  • 102
  • 120
  • I used a workaround as suggested by Chenna Reddy. I store values of primitive data types and when reading my data from the database I will recreate my objects. In case of the icon I store the codepoint and fontfamily and create a new IconData object based on this information. – jonryan Sep 25 '19 at 10:19
0

My workaround is the following:

Create database with

CREATE TABLE categories( iconData INTEGER, backgroundcolor INTEGER, name TEXT PRIMARY KEY)

My toMap() is

Map<String, dynamic> toMap() {
// Color is stored in a 32-bit integer with alpha, red, green, blue -> ARGB
int bc = backgroundcolor.alpha << 8;
bc = bc + backgroundcolor.red << 8;
bc = bc + backgroundcolor.green << 8;
bc = bc + backgroundcolor.blue;
return {
  'iconData': iconData.codePoint,
  'backgroundcolor': bc,
  'name': name
};

An I read my categories with

Future<List<Category>> getCategoriesFromDatabase() async {
  // get reference to database
  final Database db = await database;

  // Query the table for all categories
  final List<Map<String, dynamic>> maps = await db.query('categories');

  print("Categories read.");
  // Convert the List<Map<String, dynamic> into a List<Category>
  return List.generate(maps.length, (i) {
    // Construct backgroundcolor
    Color bc = Color(maps[i]['backgroundcolor']);
    // Construct iconData
    IconData id =
        IconData(maps[i]['iconData'], fontFamily: Icons.ac_unit.fontFamily);
    return Category(
      name: maps[i]['name'],
      iconData: id,
      backgroundcolor: bc,
    );
  });
}

This workaround should work for most data types. For example, I use the same solution to store dates. I save a year, month, day, ... and when reading from the db I construct a dart date.

jonryan
  • 11
  • 2