Reputation: 636
Flutter newbie here. I'm trying to parse some json in dart and am getting confused with the async nature of reading the underlying file.
How do I wait until the json has finished parsing and not just the underlying file? My confusion is that reading the file is asynchronous, but parsing the json is synchronous. Now I know that you can use await to wait for the Future to complete that's returned by loadString when reading the file. But how do I then "await" the completion of parsing the json?
jsonDecode does not accept a Future as its arguments and it runs synchronously so I can't wrap it's results into a Future(or can I?). If I could somehow get a Future< Map> _string2Item; as a result of the json parsing operation then that would solve my problem I think since I could simply: await _string2Item before doing anything.
class ItemsRepository
{
Map<String, Item> _string2Item;
//This does not work unfortunately. However, I don't want to return an instance that hasn't finished parsing the json
ItemsRepository() async
{
await init();
}
Future<String> _loadFile() async {
return await rootBundle.loadString('assets/data/item_int2string.json');
}
Future<void> init() async
{
var _fileContents = _loadFile();
_string2Item = jsonDecode(await _fileContents);
}
Item getItem(String id)
{
return _string2Item[id];
}
}
//... somewhere else in my code
ItemRepository ir = ItemRepository();
ir.getItem("42"); //this crashes because _string2Item hasn't finished parsing yet.
Any help is appreciated.
Upvotes: 0
Views: 1235
Reputation: 51692
Use:
ItemRepository ir = ItemRepository();
await ir.init();
ir.getItem('42');
Your class can be written more succinctly as:
class ItemsRepository {
Map<String, Item> _string2Item;
Future<void> init() async {
_string2Item = jsonDecode(
await rootBundle.loadString('assets/data/item_int2string.json'));
}
Item getItem(String id) => _string2Item[id];
}
You could remove the whole class and replace it with a function:
Future<Map<String, Item>> getItems() async => jsonDecode(
await rootBundle.loadString('assets/data/item_int2string.json'),
);
and use it like this
Map<String, Item> items = await getItems();
print(items['42']);
Upvotes: 1