1

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

This is the layout inside my stream builder:

enter image description here

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?

Phill Alexakis
  • 1,449
  • 1
  • 12
  • 31

0 Answers0