【问题标题】:flutter setstate rebuild only one child颤振 setstate 重建只有一个孩子
【发布时间】:2023-04-04 15:27:01
【问题描述】:

在颤振中我需要当我调用 setstate 时,它​​只重建一个小部件

我将 2 个孩子放在一个堆栈中,我需要当按下一个按钮时,只重建第二个。

bool popup = false;

Scaffold(
  appBar: AppBar(
    title: const Text('TEST'),
    actions: <Widget>[
      IconButton(                       // + BUTTON
        icon: Icon(Icons.add),
        onPressed: () {
          setState(() {
            popup = true;
          });
        },
      ),
      IconButton(                       // - BUTTON
        icon: Icon(Icons.remove),
        onPressed: () {
          setState(() {
            popup = false;
          });
      ),
    ],
  ),
  body: SafeArea(
    child: Stack(
      children: <Widget>[

        Container(                                        // FIRST WIDGET
          key: ValueKey(1),
          child: Text("Random - "+new Random().nextInt(20).toString())
        ),

        popup ? Center(child: Text("abc")) : Text("") ,   // SECOND WIDGET

      ],

    ),
  ),
);

我希望当我按下“+”按钮时,只会重新构建第二个小部件,但现在它将重新构建堆栈的所有内容。

谢谢大家。

【问题讨论】:

  • rebuild 表示根据当前状态重建整个页面。你想达到什么目的?
  • 我不能通过调用父部件的 setstate 来重建一个部件吗?
  • 我希望当我按下“+”按钮时,只会重建第二个小部件
  • 不应该考虑尽可能减少重建。我一开始也这样做了,它只是吃时间。 Flutter 够快

标签: flutter dart flutter-layout


【解决方案1】:

official docs我们可以读到:

"当在 State 上调用 setState() 时,所有后代小部件都会重建。因此,将 setState() 调用本地化到 UI 实际需要更改的子树部分。避免调用 setState() 高如果更改包含在树的一小部分中,则在树中。”

我的建议,而且我大部分时间都在使用它,是将要重建的小部件分离到一个新的 StatefulWidget 中。这样,setState 只会重建该小部件。

    class MyAppBar extends StatefulWidget
    ...
    class _MyAppBarState extends State<MyAppBar> {
    bool popup = false;

     @override
      Widget build(BuildContext context) {
        return AppBar(
           title: const Text('TEST'),
           actions: <Widget>[
           IconButton(                       // + BUTTON
             icon: Icon(Icons.add),
             onPressed: () {
               setState(() {
               popup = true;
             });
            },
           ),
          IconButton(                       // - BUTTON
            icon: Icon(Icons.remove),
            onPressed: () {
              setState(() {
              popup = false;
            });
          ),
        ],
       ), 
      }

然后在你的 Scaffold 中调用它:

Scaffold(
  appBar: MyAppBar(), 

我可以建议的其他方法是使用 ValueNotifiernotifyListeners()。请阅读此页面Avoid rebuilding all the widgets repetitively。解释得很好。

【讨论】:

  • 将小部件分离到新的 StatefulWidget 确实有帮助。
【解决方案2】:

您可以使用 StreamBuilder:

  StreamController<bool> popup = StreamController<bool>();

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('TEST'),
        actions: <Widget>[
          IconButton(                       // + BUTTON
            icon: Icon(Icons.add),
            onPressed: () => popup.add(true),
          ),
          IconButton(                       // - BUTTON
            icon: Icon(Icons.remove),
            onPressed: () => popup.add(false),
          ),
        ],
      ),
      body: SafeArea(
        child: Stack(
          children: <Widget>[
            Container(                                        // FIRST WIDGET
              key: ValueKey(1),
              child: Text("Random - "+new Random().nextInt(20).toString())
            ),
            StreamBuilder<bool>(
              stream: popup.stream,
              initialData: false,
              builder: (cxt, snapshot) {
                return snapshot.data ? Center(child: Text("abc")) : Text("");
              },
            )
          ],

        ),
      ),
    );
  }

【讨论】:

    【解决方案3】:

    从您不想更改的小部件中删除 setState。并且只对需要重建的部分使用 setState

    或者你可以考虑使用inheritedModel小部件

    【讨论】:

    • setstate 在父窗口小部件上
    【解决方案4】:

    这是一个示例,您可以从中学习如何构建继承模型小部件以仅更新特定小部件而不是整个小部件。

    https://medium.com/flutter-community/flutter-state-management-setstate-fn-is-the-easiest-and-the-most-powerful-44703c97f035

    【讨论】:

      猜你喜欢
      • 2020-08-23
      • 2020-08-05
      • 1970-01-01
      • 2020-02-16
      • 1970-01-01
      • 2019-01-14
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      相关资源
      最近更新 更多