'display loading indicator while list is being populating from an api
am new to flutter ... and am calling an api in my app and i want to display a loading indicator while the api function is finished and every thing is retrieved from the api .. how to achieve this?
class _CompaniesPageState extends State<CompaniesPage> {
getcompanies() async {
var url = 'my link';
http
.post(url, body: json.encode({ 'token': globals.token }))
.then((response) {
// print("Response body: ${response.body}");
Map data = json.decode(response.body);
final companies =
(data['Companies'] as List).map((i) => new Company.fromJson(i));
setState(() {
for (final company in companies) {
if (!company.category.contains("الراعي") &&
!company.category.contains("الشريك") &&
!company.category.contains("الداعم")) {
if (company.logo != "") {
names.add(company.name);
logos.add(company.logo);
}
}
}
});
});
}
@override
Widget build(BuildContext context) {
getcompanies();
if (globals.isguest) {
return new Directionality(
.....
);
}
}
List<Widget> createCompaniesChildren() {
List<Widget> children = List<Widget>();
for (int i = 0; i < names.length; i++) {
children.add(
new Padding(
padding: new EdgeInsets.only(right: 15.0, left: 15.0),
child: new Image.network(
logos[i],
width: 346.0,
height: 180.0,
),
),
);
children.add(
new Padding(
padding: new EdgeInsets.only(right: 15.0, left: 15.0),
child: new Center(
child: new Text(
names[i],
style: new TextStyle(color: Colors.black, fontSize: 17.0),
textAlign: TextAlign.center,
),
),
),
);
children.add(new Divider());
}
return children;
}
how can i display a loading indicator while the list is being populating and then dismiss it once it's finished??
Tried this:
body: new Padding(
padding: new EdgeInsets.only(top: 15.0),
child: new Center(
child: new FutureBuilder(
future:
getcompanies(), // your async method that returns a future
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
// if data is loaded
if (snapshot.data != null) {
return new ListView.builder(
padding: new EdgeInsets.all(8.0),
itemExtent: 20.0,
itemBuilder: (BuildContext context, int i) {
return new Center(
child: new Text(
snapshot.data[i].name,
style: new TextStyle(
color: Colors.black, fontSize: 17.0),
textAlign: TextAlign.center,
),
);
},
);
} else {
// if data not loaded yet
return new CircularProgressIndicator();
}
}
},
),
),
),
but got this error: I/flutter (31276): Another exception was thrown: A build function returned null.
Solution 1:[1]
You could use the FutureBuilder class for that purpose.
Also instead of manually creating the companies list you could use a ListView.
Something like this:
new FutureBuilder(
future: getcompanies(), // your async method that returns a future
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
// if data is loaded
return new ListView.builder(
padding: new EdgeInsets.all(8.0),
itemExtent: 20.0,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int i) {
return new Center(
child: new Text(
snapshot.data[i].name,
style: new TextStyle(color: Colors.black, fontSize: 17.0),
textAlign: TextAlign.center,
),
);
},
).build(context);
} else {
// if data not loaded yet
return new CircularProgressIndicator();
}
},
)
Solution 2:[2]
Although you have already solved or got the answer. I will show you 2 Ways.
1. Using any builder like FutureBuilder, StreamBuilder....
FutureBuilder(
future: getcompanies(), // your async method that returns a future
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.active:
case ConnectionState.waiting:
return Padding(
padding: const EdgeInsets.only(top: 20),
child: Center(
child: CircularProgressIndicator()
),
);
case ConnectionState.none:
return Center(child: Text("Unable to connect right now"));
case ConnectionState.done:
if (snapshot.hasError) {
print("Error: ${snapshot.error}");
}
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int i) {
return new Center(
child: new Text(
snapshot.data[i].name,
style: new TextStyle(color: Colors.black, fontSize: 17.0),
textAlign: TextAlign.center,
),
);
},
);
}
},
),
2. Without using builder
Put this code before API call, Like
AlertDialog alert = AlertDialog(
content: Row(children: [
CircularProgressIndicator(
backgroundColor: Colors.red,
),
Container(margin: EdgeInsets.only(left: 10), child: Text("Loading...")),
]),
);
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return alert;
},
);
api.getcompanies();
And after getting API response
var response = api.getcompanies();
Navigator.pop(context);
Note : You can put the code into a method and then call it here
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |