'flutter - futurebuilder doesn't load until textformfield is clicked

My Bad

It was problem with my future function HashtagService().getSuggestion('topic'); returning empty List before data is properly loaded. EditTopicPage didn't have any problem.

Original Question

I have text form field inside futurebuilder. When I first open page, future is not loaded. When I click on text field to enter something, future is loaded.

I want future to be loaded when the page is first opened.

class EditTopicPage extends StatefulWidget {
  const EditTopicPage({required UserProfileModel userProfile, Key? key}) : _userProfile = userProfile, super(key: key);

  final UserProfileModel _userProfile;

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

class _EditTopicPageState extends State<EditTopicPage> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final TextEditingController _controller = TextEditingController();

  List<String> _hashList = [];
  List<String> _suggestionList = [];
  late final Future<List<String>> _future;

  bool _disabled = true;

  final RegExp hashRegex = RegExp(r'^[a-z|A-Z|ㄱ-ㅎ|ㅏ-ㅣ|가-힣|ㆍ|ᆢ]*$');

  @override
  void initState() {
    _future = HashtagService().getSuggestion('topic');
    _hashList = widget._userProfile.topic.cast<String>();
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    UserProfileService _userProfileService = UserProfileService();
    final Size size = MediaQuery.of(context).size;

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: TopBar(pageTitle: "관심 대화 주제 수정", context: context),
      body: ListView(
        padding: EdgeInsets.all(16.sp),
        children: [
          FutureBuilder(
            future: _future,
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                _suggestionList = List<String>.from(snapshot.data.reversed);

                return Form(
                  key: _formKey,
                  child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        SingleLineTextFormField(
                            controller: _controller,
                            hintText: '어떤 주제로 대화하고 싶으신가요?',
                            onChanged: (value) {
                              if (value.length > 1) {
                                var lastChar = value.substring(
                                    value.length - 1);

                                if (!hashRegex.hasMatch(lastChar)) {
                                  var newHash = value.substring(
                                      0, value.length - 1);

                                  if (!_hashList.contains(newHash)) {
                                    setState(() {
                                      _hashList.add(newHash);
                                      _disabled = _hashList.isEmpty || (_hashList.length > 3);
                                    });
                                  }
                                  _controller.clear();
                                }
                              } // else if (_expHash.length == 3 && value.isNotEmpty) {
                              _formKey.currentState!.validate();
                            },
                            validator: (value) {
                              if (!hashRegex.hasMatch(value!)) {
                                return '\u26a0 한글, 영문만 가능해요';
                              }
                              return null;
                            }
                        ),
                        DefaultSpacing(),
                        Row(
                          children: [
                            Text('추천 :  ',
                              style: TextStyle(
                                fontSize: 10.sp,
                                color: Colors.grey[800],
                              ),
                            ),
                            Wrap(
                              spacing: 6.0,
                              runSpacing: 6.0,
                              children: _suggestionList.map((suggestion) =>
                                  HashtagSuggestionChip(
                                    suggestion: suggestion,
                                    type: 'topic',
                                    onPressed: () {
                                      if (!_hashList.contains(suggestion)) {
                                        setState(() {
                                          _hashList.add(suggestion);
                                          _disabled = _hashList.isEmpty || (_hashList.length > 3);
                                        });
                                      }
                                    },
                                  )).toList(),
                            ),
                          ],
                        ),
                        DefaultSpacing(),
                        Wrap(
                            spacing: 6.0,
                            runSpacing: 6.0,
                            children: _hashList.map((hashtag) =>
                                HashtagChip(
                                  hashtag: hashtag,
                                  type: 'topic',
                                  onDelete: () {
                                    setState(() {
                                      _hashList.remove(hashtag);
                                      _formKey.currentState!.validate();
                                      _disabled = _hashList.isEmpty || (_hashList.length > 3);
                                    });
                                  },
                                )).toList()
                        ),
                      ]),
                );
              }

              return CircularProgressIndicator();
            }
          ),
        ],
      ),
      floatingActionButton: FloatingSaveButton(context: context,
          text: '저장',
          width: size.width * 0.9,
          disabled: _disabled,
          onPressed: () async {
            _userProfileService.updateTopicHashtag(hashList: _hashList);

            Navigator.pop(context);

            ScaffoldMessenger.of(context).showSnackBar(SaveSnackBar());
          }),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}

Result: when the page is first opened

enter image description here

Neither hashtag nor progress indicator is shown.

After text form field is selected

enter image description here

I searched similar questions in stackoverflow, but none of the answers solved my problem.



Solution 1:[1]

Try like this

 @override
  void initState() {
setState(() {
    _future = HashtagService().getSuggestion('topic');
    _hashList = widget._userProfile.topic.cast<String>();
});
    super.initState();
  }

so your _future is async so the widget will be loaded before loading the service

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 lava