Flutter – Futurebuilder showing data only after reload

Issue

I am using future builder as follows:

 FutureBuilder<List<SurveyModel>>(
                future: Provider.of<SurveyUtils>(context, listen: false)
                    .fetchSurvey(context),
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  if (snapshot.hasData) {
                    final List surveys = snapshot.data as List;
                    return ListView.builder(
                      shrinkWrap: true,
                      itemCount: surveys.length,
                      itemBuilder: (context, index) {
                        return surveyTile(
                          surveyModel: surveys[index] as SurveyModel,
                        );
                      },
                    );
                  }
                  return const Center(
                    child: Padding(
                      padding: EdgeInsets.symmetric(vertical: 100.0),
                      child: CircularProgressIndicator(),
                    ),
                  );
                },
              ),

Future function is as follows:

Future<List<SurveyModel>> fetchSurvey(BuildContext context) async {
    print('fetch survey function call');
    List<SurveyModel> surveys = [];
    final String body = await Provider.of<HiveDB>(context, listen: false)
        .fetchData(boxName: 'surveys', title: 'surveys') as String;
    print('fetched');
    final data = json.decode(body)['data'] as List;
    surveys = data
        .map((survey) => SurveyModel.fromJson(survey as Map<String, dynamic>))
        .toList();
    print('done');
    return surveys;
  }

I am getting data from future builder only after reloading unless I reload I only get Circular progress indicator. Also print('fetch survey function call'); is not executed until reload.

Solution

future: Provider.of<SurveyUtils>(context, listen: false)
                .fetchSurvey(context),

You are not supposed to create the future in your build method. Your build method can be called many, many times and you don’t want to fetch surveys again just because someone resized their browser window or turned their device to landscape mode.

Create a variable in your state that can hold this future. Then set this variable outside of your build method. If you have no specific trigger like a button, maybe initState is the right place.

In your build method, only reference this variable. This way, you will not trigger your Future over and over again if your build method if called.

Answered By – nvoigt

Answer Checked By – Marilyn (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *