I'm trying to fetch some history data from this rest API in a FutureBuilder
. It seems the calls are too many to be handled although there must be a way to fetch the data.
A few info about the api call I'm making:
- Average server latency: 632ms
- Ideal remote api Calls: 5
- Endpoint:
https://covid-193.p.rapidapi.com/history?country=greece&day=2020-12-27}
Json Response
{
"get": "history",
"parameters": {
"country": "greece",
"day": "2020-12-27"
},
"errors": [],
"results": 1,
"response": [
{
"continent": "Europe",
"country": "Greece",
"population": 10398156,
"cases": {
"new": "+262",
"active": 120572,
"critical": 473,
"recovered": 9989,
"1M_pop": "12994",
"total": 135114
},
"deaths": {
"new": "+46",
"1M_pop": "438",
"total": 4553
},
"tests": {
"1M_pop": "314492",
"total": 3270139
},
"day": "2020-12-27",
"time": "2020-12-27T15:45:07+00:00"
}
]
}
How time scales to 37,9 sec
I'm making 5 API calls for 5 different dates (all 5 days before today) and I'm parsing the data to a Country
Object. The call will approximately take 5 x 632ms = 3610ms = 3,6 sec which sounds reasonable for a delay.
But, I have 6 different types of data to parse, for example the total deaths, I need 5 of these calls to make for 1 type, multiply it by 6 and I get a total of 30 calls. Also note that my top level StreamBuilder
can be called twice, so I'm ending up with 60 calls which translates to 37,920 ms = 37,9 sec
StreamBuilder called twice and I can't avoid it
- Related Post: Streambuilder will be called twice
This is the layout inside my stream builder:
Layouts from Top to Bottom
Calling CountryScreen
Widget to create the layout with the first parsed data
StreamBuilder(
stream: bloc.getCountryStream,
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
//Do stuff to show the total variables for each box (note this is a call to another endpoint)
return CountryScreen(
country: country,
),
}
)
CountryScreen
Map country // initialized from above
Widget build (context){
return column(children:[
InfoCard(
title: "Total Cases",
iconColor: Color(0xFFFF8C00),
effectedNum: "${country['totalcases']}",
country: country['country'],
searchFor: "Total Cases",
),
InfoCard(...),
...
...
InfoCard(
title: "New Deaths",
iconColor: Colors.red,
effectedNum: "${country['newdeaths']}",
country: country['country'],
searchFor: "Total Cases",
)
]);
}
Info Card
Widget build(context)
{
return Expanded(
child: LineReportChart(
country: country, searchFor: searchFor),
);
}
LineReportChart
class LineReportChart extends StatefulWidget {
final String country;
final String searchFor;
LineReportChart({this.country, this.searchFor});
@override
_LineReportChart createState() =>
_LineReportChart(country: country, searchFor: searchFor);
}
class _LineReportChart extends State<LineReportChart> {
String country;
String searchFor;
_LineReportChart({this.country, this.searchFor});
List<FlSpot> spots = [];
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: getSpots(),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (!snapshot.hasData) {
return AspectRatio(
aspectRatio: 2.2,
child: SizedBox(
child: CircularProgressIndicator(),
));
}
spots = snapshot.data;
return AspectRatio(
aspectRatio: 2.2,
child: LineChart(
LineChartData(
gridData: FlGridData(
show: false,
),
borderData: FlBorderData(
show: false,
),
titlesData: FlTitlesData(show: false),
lineBarsData: [
LineChartBarData(
spots: spots,
isCurved: true,
dotData: FlDotData(show: false),
belowBarData: BarAreaData(show: false),
colors: [kPrimaryColor],
barWidth: 3),
]),
),
);
});
}
Future<dynamic> getSpots() async {
return FetchCountry.getNewCasesChart(country, searchFor);
}
Rest API Call
getNewCasesChart method
static Future<List<FlSpot>> getNewCasesChart(country, searchFor) async {
//do 5 calls and the parsing for each one. I didn't include it as the post is already long.
print('called function for fetch data');
List<FlSpot> chartPoints;
switch (searchFor) {
case "Total Cases":
await Future.delayed(Duration(seconds: 2));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
FlSpot(1, 1),
];
break;
case "Total Deaths":
await Future.delayed(Duration(seconds: 4));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
];
break;
case "Recovered":
await Future.delayed(Duration(seconds: 3));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
FlSpot(3, 2.1),
];
break;
case "New Cases":
await Future.delayed(Duration(seconds: 6));
chartPoints = [
FlSpot(1, 1.5),
FlSpot(0, .5),
FlSpot(2, .5),
];
break;
case "Critical":
await Future.delayed(Duration(seconds: 5));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
FlSpot(3, .5),
FlSpot(5, .5),
];
break;
case "New Deaths":
await Future.delayed(Duration(seconds: 3));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
];
break;
default:
}
return chartPoints;
}
Is there any way to reduce the total calls on the top level layout?