如何正确使用FutureBuilder中的setState?

cha*_*ark 1 checkbox setstate dart flutter flutter-futurebuilder

我正在制作一个页面,其中包含一些相互交互的保管箱和一个 Futurebuilder 包装的 ListView。

当 Dropbox 发生更改并单击复选框时,我会调用“setState”。但是,由于checkbox的onChanged中的setState,Futurebuilder不断被调用,ListView被重建。因此,当单击复选框时,整个列表视图都会闪烁,如下视频所示。

问题视频

我想保留列表视图并仅更新复选框。有人可以帮助我吗?谢谢。

完整的代码是

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(),
      ],
    );
  }
Run Code Online (Sandbox Code Playgroud)

列表视图代码

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;                              
                        });
                      },
                    );
                  },
                ),
              );
            }
          }
        });
  }
Run Code Online (Sandbox Code Playgroud)

下拉代码

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
            });
          }
        });
  }
Run Code Online (Sandbox Code Playgroud)

Chr*_*ore 5

请阅读FutureBuilder 文档。它指出:

future 必须提前获得,例如在 State.initState、State.didUpdateWidget 或 State.didChangeDependency 期间。在构造 FutureBuilder 时,不得在 State.build 或 StatelessWidget.build 方法调用期间创建它。如果 future 与 FutureBuilder 同时创建,那么每次重建 FutureBuilder 的父级时,异步任务都会重新启动。

正如文档所述,获取未来initState并将其存储在您的州中。

Future future;
@override
void initState() {
  future = AptNameListView(widget.ReceiveArgs);
  super.initState();
}


Widget AptListview() {
    return FutureBuilder<List<String>>(
        future: future,
        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;                              
                        });
                      },
                    );
                  },
                ),
              );
            }
          }
        });
  }
Run Code Online (Sandbox Code Playgroud)