【问题标题】:Flutter: setState() working, but not re-renderingFlutter:setState() 工作,但不重新渲染
【发布时间】:2019-09-16 00:27:06
【问题描述】:

我正在通过制作一个小新闻应用来学习 Flutter。每个选项卡都有一个新闻文章小部件列表,其中包含一个图像、一个标题、一个描述、一个“了解更多”链接按钮,以及一个用于扩展或缩小小部件以包含或隐藏描述的按钮。

我现在的问题是扩展部分。当我按下按钮展开小部件时,setState() 被调用并且我的布尔值_expanded 被切换。但是,我认为它不会被重新渲染,因为小部件不会扩展。正如您将在我的代码中看到的那样,我有一个内联条件作为_expanded ? option if its expanded : option if its not expanded 形式的列表中的小部件。我已经通过将! 放在内联条件前面来验证这些小部件是我想要的,它们会显示它们应该显示的内容,所以我很困惑。

目前我唯一的想法是它可能与状态是不可变的事实有关,并且也许我正在尝试更改状态而不是替换和重新渲染。有任何想法吗?谢谢!

我试图只包含必要的内容,但这里是一些代码:

class NewsList extends StatefulWidget {
  NewsList({this.keyword});
  final String keyword;

  @override
  createState() => NewsListState(keyword: keyword);
}

class NewsListState extends State<NewsList> {
  NewsListState({this.imageURLs, this.titles, this.texts, this.keyword});
  final List<String> imageURLs;
  final List<String> titles;
  final List<String> texts;
  final String keyword;

  List<NewsArticle> _newsArticles = List<NewsArticle>();

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

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

  void _populateNewsArticles() {
    WebService().load(NewsArticle().all(keyword)).then((newsArticles) => {
          setState(() {
            _newsArticles = newsArticles;
          })
        });
  }

  Widget _buildNewsArticles(BuildContext build, int index) {
    bool _expanded = false;
    return Container(
      decoration: BoxDecoration(
          borderRadius: BorderRadius.all(const Radius.circular(10)),
          color: Colors.white,
          boxShadow: [
            BoxShadow(
                color: Colors.grey[300],
                blurRadius: 20,
                spreadRadius: 3,
                offset: Offset(5, 5))
          ]),
      child: Column(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                _newsArticles[index].urlToImage == null
                    ? AssetImage(Constants.NEWS_PLACEHOLDER_IMAGE_ASSET_URL)
                    : CachedNetworkImage(
                        imageUrl: _newsArticles[index].urlToImage),
                Padding(padding: const EdgeInsets.symmetric(vertical: 5)),
                Text(
                  _newsArticles[index].title,
                  textAlign: TextAlign.left,
                  style: TextStyle(
                    fontSize: 25,
                    fontWeight: FontWeight.w700,
                    height: 0.8,
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.fromLTRB(4, 15, 4, 0),
                  child: Platform.isIOS
                      ? CupertinoButton.filled(
                          child: Text(
                            "Learn More",
                            style: TextStyle(fontSize: 17),
                          ),
                          onPressed: () =>
                              navigateToUrl(_newsArticles[index].url),
                          pressedOpacity: 0.6,
                        )
                      : RaisedButton(
                          onPressed: () =>
                              navigateToUrl(_newsArticles[index].url),
                          color: Color.fromRGBO(0, 122, 255, 1.0),
                          animationDuration: Duration(milliseconds: 1000),
                          child: Text(
                            "Learn More",
                            style: TextStyle(fontSize: 16, color: Colors.white),
                          ),
                        ),
                ),
                !_expanded ? Text("test description") : Container(),
                !_expanded
                    ? IconButton(
                        icon: Icon(Icons.keyboard_arrow_up),
                        onPressed: () => setState(() {
                          _expanded = !_expanded;
                        }),
                      )
                    : IconButton(
                        icon: Icon(Icons.keyboard_arrow_down),
                        onPressed: () {
                          setState(() {
                            debugPrint(_expanded.toString());
                            _expanded = !_expanded;
                            debugPrint(_expanded.toString());
                          });
                        },
                      ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget build(BuildContext context) {
    return ListView.separated(
      separatorBuilder: (BuildContext context, int index) =>
          Padding(padding: const EdgeInsets.symmetric(vertical: 15)),
      padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 30),
      itemBuilder: _buildNewsArticles,
      itemCount: _newsArticles.length,
    );
  }
}

【问题讨论】:

    标签: flutter dart state setstate state-management


    【解决方案1】:

    _expanded 是在buildNewsArticles 方法中定义和初始化的局部变量。因此,每次buildNewsArticles 运行时,_expanded 都会被初始化为 false。

    您应该将_expanded 移出方法,使其成为NewsListState 的成员变量。

    【讨论】:

    • 这种工作。也许问题只是因为它是一个 NewsList 小部件而不是单个小部件,但是当我展开一个小部件时,它们都会展开。有没有办法为单个新闻文章小部件设置扩展变量?
    • 如果您需要跟踪每个新闻item 的展开状态,那么您需要为每个新闻项目创建一个状态对象,每个都具有一个_expanded 属性。 _expanded 成为 NewsItemState 的一个属性
    • 这应该会有所帮助。只需在其中创建带有 setstate 的有状态小部件。 stackoverflow.com/questions/61142775/…
    猜你喜欢
    • 2018-11-14
    • 2020-02-13
    • 2011-01-20
    • 2017-04-19
    • 2018-02-27
    • 1970-01-01
    • 2011-08-19
    • 1970-01-01
    • 2017-02-24
    相关资源
    最近更新 更多