从列表中调用时不会更新 flutter 小部件

flutter widget not being updated when called from a list

我之前在这里问过一个关于小部件未更新的问题:

我得到了一个很好的答案,它向我解释了更多关于状态如何工作的信息,我进一步试验了一点,现在有一个问题,即即使我在 setstate 中更新状态,我在列表中的小部件也没有更新。

问题中未更新的Widget 是testBoxList 列表中添加到列表后的TestBoxNumber 小部件。我意识到,如果我将构建器更改为 return 小部件本身,而不是从它工作的列表中,我不确定为什么会这样!

再次感谢任何帮助,我希望这也能帮助面临同样问题的人:)

主页代码

class TestPage extends StatefulWidget {
  static const id = "test_page";

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

class _TestPageState extends State<TestPage> {
  List testBoxList = [];
  List testSlideList = [];
  List testParamList = [];

  void updateFunc(ind, newVal) {
    setState(() {
      testParamList[ind] = newVal;
    });
  }

  void addSlider() {
    setState(() {
      double slideValue = 0;
      testParamList.add(slideValue);
      int boxIndex = testParamList.length - 1;

      testBoxList.add(TestBoxNumber(
        numberDisplay: testParamList,
        boxIndex: boxIndex,
      ));
      testSlideList.add(TestSlider(
        testValue: testParamList,
        updateFunc: updateFunc,
        boxIndex: boxIndex,
      ));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          addSlider();
        },
      ),
      body: Padding(
        padding: const EdgeInsets.all(30.0),
        child: ListView(
          children: [
            Text("Test Page"),
            // Builder for viewers
            ListView.builder(
              shrinkWrap: true,
              physics: ClampingScrollPhysics(),
              itemCount: testBoxList.length,
              itemBuilder: (BuildContext ctx, int index) {
                return testBoxList[index];
                // return Text(testParamList[index].toString());
                // return TestBoxNumber(
                //     numberDisplay: testParamList, boxIndex: index);
              },
            ),
            // Builder for sliders
            ListView.builder(
              shrinkWrap: true,
              physics: ClampingScrollPhysics(),
              itemCount: testSlideList.length,
              itemBuilder: (BuildContext ctx, int index) {
                return testSlideList[index];
              },
            ),
          ],
        ),
      ),
    );
  }
}

TestBoxNumber 小部件

class TestBoxNumber extends StatelessWidget {
  final List numberDisplay;
  final int boxIndex;

  TestBoxNumber({required this.numberDisplay, required this.boxIndex});

  Widget build(BuildContext context) {
    return Text(this.numberDisplay[this.boxIndex].toString());
  }
}

滑块小部件

class TestSlider extends StatefulWidget {
  List testValue;
  dynamic updateFunc;
  int boxIndex;

  TestSlider({
    required this.testValue,
    required this.updateFunc,
    required this.boxIndex,
  });

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

class _TestSliderState extends State<TestSlider> {
  // double curValue = widget.testValue;

  @override
  Widget build(BuildContext context) {
    double curValue = widget.testValue[widget.boxIndex];

    return Slider(
      activeColor: themeData.primaryColorLight,
      value: curValue,
      min: 0,
      max: 100,
      divisions: 50,
      label: curValue.round().toString(),
      onChanged: (double value) {
        setState(() {
          curValue = value;
        });
        widget.updateFunc(widget.boxIndex, value);
      },
    );
  }
}

又是我)

好的,现在的问题是您正在使用存储在列表中的小部件,而不是再次创建小部件:

你不应该这样做:

ListView.builder(
              shrinkWrap: true,
              physics: ClampingScrollPhysics(),
              itemCount: testBoxList.length,
              itemBuilder: (BuildContext ctx, int index) {
                return testBoxList[index];
                // return Text(testParamList[index].toString());
                // return TestBoxNumber(
                //     numberDisplay: testParamList, boxIndex: index);
              },
            )

但是 return 新的 TestBoxNumber 小部件(您实际上已经对它进行了评论,但不确定您为什么这样做):

ListView.builder(
                  shrinkWrap: true,
                  physics: ClampingScrollPhysics(),
                  itemCount: testBoxList.length,
                  itemBuilder: (BuildContext ctx, int index) {
                    return TestBoxNumber(numberDisplay: testParamList, boxIndex: index);
                  },
                )

所以你将从头开始渲染小部件,而不是从内存(列表)中提取它并导致一些奇怪的事情。 Flutter 针对此类重新渲染进行了相当优化。

所以总结以上所有内容:只需将数据传递到构建方法中的小部件。不要将小部件存储在内存中以便以后重用

UPD:您也可以将 double(我们称之为 yourDoubleValue)传递给 TestBoxNumber 而不是列表和索引。然后使用 Text('$yourDoubleValue');