Reputation: 181
I'm trying to read a json file named mood.json
and parse it to a list named "data", but when I run setState()
, the data
never changed, any help about this problem? The code looks like this:
class DisplayPage extends StatefulWidget {
@override
_DisplayPageState createState() => new _DisplayPageState();
}
class _DisplayPageState extends State<DisplayPage> {
List _data = [];
Directory dir;
File jsonFile;
String jsonPath;
Future getData() async {
dir = await getApplicationDocumentsDirectory();
jsonPath = dir.path + "/" + "mood.json";
jsonFile = new File(jsonPath);
setState(() {
_data = json.decode(jsonFile.readAsStringSync());
});
}
@override
void initState() {
super.initState();
getData();
print(_data.length);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Mood')
),
body: new ListView.builder(
itemCount: _data.length,
itemBuilder: (BuildContext context, int index) {
return new Card(
child: new Text(_data[index]["title"]),
);
},),
);
}
}
Upvotes: 17
Views: 45229
Reputation: 450
EDIT* Sorry i was wrong, you can call async method from initState(), just call it without await
@override
void initState() {
super.initState();
/// getData(); /// this is an async method, and it's return a future.
/// you can use await instead so the code bellow getData() method execution
/// will be waiting for it to complete first.
/// Here it is :
getData();
print(_data.length); /// This print now will waiting until the getData completed
}
here is some references : https://dart.dev/codelabs/async-await#working-with-futures-async-and-await
Upvotes: 0
Reputation: 61
You should use "async" outside "setState" method.
Note: Use "await" for waitting for the response.
Future getData() async {
dir = await getApplicationDocumentsDirectory();
jsonPath = dir.path + "/" + "mood.json";
jsonFile = new File(jsonPath);
//Use async outside
var json = await json.decode(jsonFile.readAsStringSync());
//Change values on setState
setState(() {
_data = json;
});
}
Upvotes: 1
Reputation: 21
As mentioned in this post, use
WidgetsBinding.instance.addPostFrameCallback((_) => setState(...));
instead of just
setState(...)
Upvotes: 2
Reputation: 42333
I think your problem may be something else; I took your code and changed the network call to just wait 5 seconds and then return some dummy data and it worked fine.
Future getData() async {
await new Future.delayed(const Duration(seconds: 5));
setState(() {
_data = [
{"title": "one"},
{"title": "two"},
];
});
}
You should put a breakpoint inside your setState
call to ensure it's actually being called and that the data being assigned to _data
is as you expect.
Upvotes: 12