I am trying to show real time http json data mtgCardNames
using buildResults
. The data seem to be passed down successfully (they are printed out correctly) but somehow they are not displayed on the screen. To understand the situation, I tried to display some other data (search query
and testList
), they show on the screen as expected.
Why is this happening?
I overrided all the required 4 methods, but only paste the buildResults
here to be brief.
@override
Widget buildResults(BuildContext context) {
List<MTGCard> mtgCards = [];
List<Text> mtgCardNames = [];
GetHTTP getHTTP = GetHTTP();
getHTTP.getData().then((usersFromServer) {
mtgCards = usersFromServer;
for (MTGCard c in mtgCards){
print(c.name); // <= can print out as expected
mtgCardNames.add(Text(c.name));
}
});
List<Text> testList = [
Text('a'),
Text('aa'),
Text('aaa'),
];
return Column(
children: <Widget>[
Text(query),
Column(
children: mtgCardNames,
),
Column(
children: testList,
),
],
);
}
For this moment, the http data is not based on the query, it is hard coded url but real time data. I am running on Ubuntu and my flutter doctor shows no issue.
Any suggestion or help is highly appreciated!
The problem is that network call getData()
is executed asynchronously:
1) You call getData()
2) Synchronous code continues to execute: return Column(...)
is called while mtgCardNames
is still empty
3) You see empty column on the screen
4) Network call finishes, then(...)
is executed and mtgCardNames
is populated
To actually display column with data from network call, you should return one widget while it's loading and another one after. One way is to use FutureBuilder
. Basic idea is
@override
Widget buildResults(BuildContext context) {
GetHTTP getHTTP = GetHTTP();
return FutureBuilder<List<MTGCard>>(
future: getHTTP.getData(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Text('Loading...');
return Column(
children: <Widget>[
Text(query),
for (MTGCard c in snapshot.data)
Text(c.name),
],
);
},
);
}
But there are some more details. E.g. it’s not a good idea to put network call in a build() method. Also you can show some error widget if network call fails. See details in tutorial