Solved: Flutter - Futurebuilder showing data only after reload

Question

Asked by Asim B on November 24, 2021 (source).

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.

Answer

Question answered by nvoigt (source).

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.

DART FLUTTER FLUTTER-FUTUREBUILDER
SHARE: