wierdo
wierdo

Reputation: 285

How to render my widget after data loading completed in Flutter

What I'm trying to do After sign in, showing HomeScreen which has a listview. This listview is showing data coming from an API. So, it takes a little bit time to load. I want to render my HomeScreen after loading is completed an my listview is full of data.

What I've already done I have an api helper class that does api works. It has a static method which is getting data for my listview and returning a list. This is my getFixtureData method.

 static Future<List<Fixtures>> getFixtureData() async {
    Map<String, String> queryParameters = {
      'league': '78',
      'next': '20',
    };

    http.Response response = await http.get(
      getUrl('fixtures', queryParameters),
      headers: requestHeaders,
    );

    print(response.body);

    if (response.statusCode == 200) {
      String data = response.body;
      List<dynamic> result = jsonDecode(data)['response'];

      for (int i = 0; i < result.length; i++) {
        Fixtures fixture = Fixtures();

        fixture.leagueID = jsonDecode(data)['response'][i]['league']['id'];
        fixture.country = jsonDecode(data)['response'][i]['league']['country'];
        fixture.leagueName = jsonDecode(data)['response'][i]['league']['name'];
        fixture.fixtureID = jsonDecode(data)['response'][i]['fixture']['id'];

        //get Odds to match with fixtures by fixtureID
        await getOddsData(fixture.fixtureID);

        fixture.dateTime =
            DateTime.parse(jsonDecode(data)['response'][i]['fixture']['date']);
        fixture.homeTeam =
            jsonDecode(data)['response'][i]['teams']['home']['name'];
        fixture.awayTeam =
            jsonDecode(data)['response'][i]['teams']['away']['name'];
        fixture.status =
            jsonDecode(data)['response'][i]['fixture']['status']['long'];
        fixture.homeGoals = jsonDecode(data)['response'][i]['goals']['home'];
        fixture.awayGoals = jsonDecode(data)['response'][i]['goals']['away'];
        fixture.htScoreHome =
            jsonDecode(data)['response'][i]['score']['halftime']['home'];
        fixture.htScoreAway =
            jsonDecode(data)['response'][i]['score']['halftime']['away'];
        fixture.ftScoreHome =
            jsonDecode(data)['response'][i]['score']['fulltime']['home'];
        fixture.ftScoreAway =
            jsonDecode(data)['response'][i]['score']['fulltime']['away'];

        if (oddsList.length > 0) {
          for (int j = 0; j < oddsList.length; j++) {
            if (oddsList[j].fixtureID == fixture.fixtureID) {
              fixture.homeOdds = oddsList[j].homeOdds;
              fixture.drawOdds = oddsList[j].drawOdds;
              fixture.awayOdds = oddsList[j].awayOdds;
              fixture.bookmakerName = oddsList[j].bookmakerName;
              FootballApi.fixtureList.add(
                  fixture); // this line must be here. If there is no odds of that match, it should not be in fixtureList
            }
          }
        }
      }
    } else {
      print('statusCode: ' + response.statusCode.toString());
    }

    return FootballApi.fixtureList;
  }

I'm calling this method in my stateful widget(HomeScreen) which have a listview that I feed it with the list getFixtureData method returned. I'm calling it in initState of HomeScreen. This is the relevant code.

class HomeScreen extends StatefulWidget {
  static String id = 'home_screen';

  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  int gameIndex = 0;
  String gameTitle = 'Soccer';
  int selectedCategoryIndex = 0;
  List<Fixtures> fixtureList = List<Fixtures>();


  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getFixture();
  }

  Future<List<Fixtures>> getFixture() async {
    fixtureList = await FootballApi.getFixtureData();
    return fixtureList;
  }

And this part is the where I pass the data to listview in HomeScreen.

      Stack(children: [
        AppListView(
          matchList: FootballApi.fixtureList,
          //callback function brings the matchCounter value from ListView class
          onChange: (value) {
            setState(() {
              matchCounter = value;
            });
          },
          finalBetList: (value) {
            setState(() {
              betList = value;
            });
          },
        ),

The problem is; when user signs in, he is viewing my home screen with an empty listview. After a few seconds listview is loaded. I want to render HomeScreen after my listview loaded fully. What is the best way for that?

Upvotes: 0

Views: 6966

Answers (1)

Ali Bayram
Ali Bayram

Reputation: 7931

use FutureBuilder widget to build widgets after getting data from async functions;

FutureBuilder<List<Fixtures>>(
  future: getFixture(),
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      List<Fixtures> yourResponseDataFromAsync = snapshot.data;
      return AppListView(
        matchList: yourResponseDataFromAsync,
        //callback function brings the matchCounter value from ListView class
        onChange: (value) {
          setState(() {
            matchCounter = value;
          });
        },
        finalBetList: (value) {
          setState(() {
            betList = value;
          });
        },
      );
    }
    return CircularProgressIndicator();
  },
),

Upvotes: 8

Related Questions