How to use setState in FutureBuilder properly?

Issue

I’m making a page which contains some dropboxes which interact each other and a Futurebuilder wrapped ListView.

I’m calling ‘setState’ when Dropbox changes and checkbox is clicked.
However, because of the setState in checkbox’s onChanged, the Futurebuilder keeps being called and the ListView is rebuilded.
Therefore the entire Listview is blinkning when checkbox is clicked like the video below.

Problem Video

I want to keep the Listview and update only checkbox.
Is there anyone who can help me?
Thank you.

The full code is

class _StatefulDialogWidgetState extends State<StatefulDialogWidget> {
  ....   

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // Dropdown's
        Dropdown(0, widget.ReceiveArgs, _lListOfDepthList),
        Dropdown(1, widget.ReceiveArgs, _lListOfDepthList),
        Dropdown(2, widget.ReceiveArgs, _lListOfDepthList),
        Dropdown(3, widget.ReceiveArgs, _lListOfDepthList),
        Dropdown(4, widget.ReceiveArgs, _lListOfDepthList),
        
        // Listview with FutureBuilder
        AptListview(),
      ],
    );
  }

ListView Code

Widget AptListview() {
    return FutureBuilder<List<String>>(
        future: AptNameListView(widget.ReceiveArgs),
        builder: (context, snapshot) {
          if (_bLastDepth == false) {
            return Text("Select Address");
          } else {
            if (snapshot.hasData == false || snapshot.data.isEmpty == true) {
              return CircularProgressIndicator();
            } else {
              return Expanded(
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: _AptNameList.length,
                  itemBuilder: (context, index) {
                    //return new Text("${_AptName[index]}");
                    return CheckboxListTile(
                      title: Text(_AptNameList[index]),
                      value: _isAptChecked[index],
                      onChanged: (value) {
                        setState(() {                   //  SetState in FutureBuilder
                          _isAptChecked[index] = value;                              
                        });
                      },
                    );
                  },
                ),
              );
            }
          }
        });
  }

Dropdown Code

Widget Dropdown(int nDepth, ArgumentClass ReceiveArgs,
      List<List<String>> ListOfDepthList) {
    String _Value = "";
    List<DropdownMenuItem<String>> _itemList = null;
    if (ListOfDepthList.length <= nDepth) {
      _Value = "";
      _itemList = null;
    } else {
      _Value = _SelectedAddressList[nDepth];
      _itemList = GetMainItem(ListOfDepthList[nDepth]);
    }
    return DropdownButton(
        value: _Value,
        items: _itemList,
        onChanged: (value) {
          if (value.compareTo(GlobalObject().startMessage) != 0) {
            setState(() {
              .....
              // setState in Dropdown
            });
          }
        });
  }

Solution

I solve this problem by

  1. Call the future function in dropbox’s setState
  2. Change the Futurebuilder to Listview.

It prevented updating of listview in futurebuilder when SetState is called.

Answered By – chan hong Park

Answer Checked By – Marie Seifert (FlutterFixes Admin)

Leave a Reply

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