jonataslaw / get_storage

A fast, extra light and synchronous key-value storage to Get framework
MIT License
369 stars 83 forks source link

Problem saving and restoring list of string #60

Open dadokkio opened 3 years ago

dadokkio commented 3 years ago

If I save a List<String> I'm able to use and modify it during app run but at the following restart the app crashes with error:

type 'List<dynamic>' is not a subtype of type 'List<String>?' in type cast

There is something I need to specify during write or read to manage list properly?

My actual code to restore:

  @override
  void initState() {
    super.initState();
    try {
      _savedDevices = box.read('saved_devices') ?? <String>[];
    } catch (e) {
      List<dynamic> tmp = box.read('saved_devices');
      _savedDevices = tmp.map((item) => item.toString()).toList();
    }
  }

where _savedDevices is a List<String> saved as box.write('saved_devices', _savedDevices);

Thanks

Vlad-Adrian commented 3 years ago

I have the same issue, unfortunately couldn't find a workaround for now. @jonataslaw any help please?

markst commented 3 years ago

Also experiencing a similar issue. Works fine first time round, but fails after relaunch with the following:

Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<Map<String, String>>?' in type cast E/flutter (19263): #0 StorageImpl.read 

I'm attempting to store values in a list of maps:

final _downloads = ReadWriteValue("downloads", List<Map<String, String>>.empty(growable: true), () => GetStorage('downloads'));
markst commented 3 years ago

@Vlad-Adrian wonder if a workaround could be to cast to List<dynamic> then cast back when writing?

    try {
      List<dynamic> downloads = _downloads.val;
      downloads.add(tags);
      _downloads.val = downloads as List<Map<String, String>>;
    } catch (t) {
      print(t);
    }
Vlad-Adrian commented 3 years ago

@markst so you are having an issue when writing?

It is strange that you have problems when writing. Did you try with Get.write(key, value); and read it back with Get.read(key);? When you read it back from memory you can cast it from dynamic to String and should be fine. It doesn't matter if you cast it to String when you save(write) it, after an app restart, the type will get lost.

I hope it helps. In any case let me know :)

Apollo108 commented 3 years ago

I also had strange behaviour while saving List, and now I always encode it to a string, and then decode it back (e.g.: List.from(json.decode(map['integers'] as String) as List)). Works fine.

WingCH commented 3 years ago

My Solution

write

Future<void> saveImageList(List<ImageModel> imageModels) async {
      List<Map<String, dynamic>> rawData =
          imageModels.map((e) => e.toJson()).toList();
      await box.write(imageListsKey, rawData);
  }

read

List<dynamic>? result = box.read(imageListsKey);
if(result != null) {
List<ImageModel> modelList = result.map<ImageModel>((element) {
          return ImageModel.fromJson(element);
        }).toList();
}
songgnqing commented 7 months ago
_savedDevices = box.read<List<dynamic>>('saved_devices').cast<String>() ?? <String>[];

json.decode a list return List<dynamic>. You need to call cast to change the item type form dynamic to String.