setState 不重建小部件

时间:2021-07-09 04:03:36

标签: flutter dart setstate

我是 Flutter/Dart 开发的新手,但我遇到了调用 setState 没有重建小部件的问题。

我试图在用户界面中显示用户在点击它们以及将它们添加到另一个列表时选择的类型。重新打开模式时,点击选择的颜色应该会发生变化,但没有任何变化,但类型实际上已添加到另一个列表中。

这是代码


class GenresPicker extends StatefulWidget {

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

class _GenresPickerState extends State<GenresPicker> {

  List<Genre> _selectedGenres = [];

  @override
  void initState() {
    super.initState();
  }

  addGenre(genre) {
    setState(() {
      _selectedGenres.add(genre);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      padding: EdgeInsets.all(20),
      child: FutureBuilder<List<Genre>>(
        future: fetchGenres(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return Container(
              alignment: Alignment.center,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    "MODAL BOTTOM SHEET EXAMPLE",
                    style: TextStyle(
                        fontStyle: FontStyle.italic,
                        letterSpacing: 0.4,
                        fontWeight: FontWeight.w600),
                  ),
                  SizedBox(
                    height: 20,
                  ),
                  ElevatedButton(
                    onPressed: () {
                      showModalBottomSheet(
                        context: context,
                        builder: (context) {
                          return Column(
                            children: <Widget>[
                              Text("Genres:"),
                              Expanded(
                                child: GridView.builder(
                                  gridDelegate:
                                      SliverGridDelegateWithMaxCrossAxisExtent(
                                          maxCrossAxisExtent: 100,
                                          childAspectRatio: 4 / 2,
                                          crossAxisSpacing: 10,
                                          mainAxisSpacing: 10),
                                  itemCount: snapshot.data!.length,
                                  itemBuilder: (BuildContext ctx, index) {
                                    return Container(
                                      alignment: Alignment.center,
                                      child: GestureDetector(
                                        onTap: () {
                                          //_selectedGenres
                                          //    .add(snapshot.data![index]);
                                          if (!_selectedGenres.contains(
                                              snapshot.data![index])) {
                                            addGenre(snapshot.data![index]);
                                          }
                                        },
                                        child: Text(snapshot.data![index].name),
                                      ),
                                      decoration: BoxDecoration(
                                          color: _selectedGenres.contains(
                                                  snapshot.data![index])
                                              ? Colors.blue[200]
                                              : Colors.blue[50],
                                          borderRadius:
                                              BorderRadius.circular(15)),
                                    );
                                  },
                                ),
                              ),
                            ],
                          );
                        },
                      );
                    },
                    child: Text(
                      'Click Me',
                      style: TextStyle(
                          color: Colors.white,
                          fontWeight: FontWeight.w600,
                          letterSpacing: 0.6),
                    ),
                  ),
                ],
              ),
            );
          } else if (snapshot.hasError) {
            return Text("${snapshot.error}");
          }
          // By default, show a loading spinner.
          return Center(child: CircularProgressIndicator());
        },
      ),
    );
  }
}

注释代码是一种解决方法,以某种方式工作得更好,但不是预期的结果,因为在点击并重新打开模式时,实际上会显示选择。

提前致谢。

1 个答案:

答案 0 :(得分:3)

发生这种情况只是因为您在 showModalBottomSheet(Dialog) 中使用了 setState。

确保每当您希望刷新对话框内的数据时,使用 StatefulBuilder 包装子项,并使用该构建器的 setState 刷新列表,它会起作用。

检查示例

import 'package:flutter/material.dart';

class BottomRefreshExample extends StatefulWidget {
  @override
  _BottomRefreshExampleState createState() => _BottomRefreshExampleState();
}

class _BottomRefreshExampleState extends State<BottomRefreshExample> {
  List<String> _selectedListData = [];
  List<String> _responseListData = ["Add1", "Add2", "Add3", "Add4", "Add5"];

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      padding: EdgeInsets.all(20),
      child: Container(
        alignment: Alignment.center,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              "MODAL BOTTOM SHEET EXAMPLE",
              style: TextStyle(fontStyle: FontStyle.italic, letterSpacing: 0.4, fontWeight: FontWeight.w600, fontSize: 12),
            ),
            SizedBox(
              height: 20,
            ),
            ElevatedButton(
              onPressed: () {
                showModalBottomSheet(
                  context: context,
                  builder: (context) {
                    return StatefulBuilder(builder: (context, setNewState) {
                      return Column(
                        children: <Widget>[
                          Expanded(
                            child: GridView.builder(
                              gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                                  maxCrossAxisExtent: 100, childAspectRatio: 4 / 2, crossAxisSpacing: 10, mainAxisSpacing: 10),
                              itemCount: _responseListData.length,
                              itemBuilder: (BuildContext ctx, index) {
                                return Container(
                                  alignment: Alignment.center,
                                  child: GestureDetector(
                                    onTap: () {
                                      if (!_selectedListData.contains(_responseListData[index])) {
                                        setNewState(() {
                                          _selectedListData.add(_responseListData[index]);
                                        });
                                      }
                                    },
                                    child: Text(_responseListData[index]),
                                  ),
                                  decoration: BoxDecoration(
                                      color: _selectedListData.contains(_responseListData[index]) ? Colors.blue[200] : Colors.blue[50],
                                      borderRadius: BorderRadius.circular(15)),
                                );
                              },
                            ),
                          ),
                        ],
                      );
                    });
                  },
                );
              },
              child: Text(
                'Open Bottom Sheet',
                style: TextStyle(color: Colors.white, fontWeight: FontWeight.w600, letterSpacing: 0.6),
              ),
            ),
          ],
        ),
      ),
    );
  }
}