如何从另一个小部件设置状态?

Posted

技术标签:

【中文标题】如何从另一个小部件设置状态?【英文标题】:How to set state from another widget? 【发布时间】:2018-10-30 00:20:00 【问题描述】:

我正在尝试从 Flutter 中的不同小部件更改状态。例如,在以下示例中,我在几秒钟后设置状态。

下面是代码:

class _MyAppState extends State<MyApp> 

  int number = 1;

  @override
  void initState() 
    super.initState();
    new Future.delayed(new Duration(seconds: 5)).then((_) 
      this.setState(() => number = 2);
      print("Changed");
    );
  

  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      body: new Center(
        child: new FlatButton(
          color: Colors.blue,
          child: new Text("Next Page"),
          onPressed: () 
            Navigator.of(context).push(new MaterialPageRoute(
              builder: (BuildContext context) => new StatefulBuilder(builder: (BuildContext context, setState) =>new MySecondPage(number))
            ));
          ,
        ),
      ),
    );
  

我尝试使用InheritedWidget,但除非我将它包裹在我的***小部件周围,否则这将不起作用,这对于我正在尝试做的事情是不可行的(上面的代码是我所做的简化)我试图实现)。

关于在 Flutter 中实现这一目标的最佳方式有什么想法吗?

【问题讨论】:

相似,如果不相同:) ***.com/questions/52761888/… @giorgio79 这个问题是在您链接的问题之前提出的? 【参考方案1】:

实际上最有效的方法是在 Flutter 中使用 BLoC 包,并从小部件树的顶部实现它,这样所有继承的小部件都可以使用相同的 bloc。如果您以前使用过 android - 它的工作方式类似于 Android 架构组件 - 您将数据和状态管理与 UI 分开 - 因此您无需在 UI 中设置状态,而是使用块来管理状态。因此,您可以设置和访问相同的数据 - 从任何从实现 bloc 的顶部小部件继承的小部件中设置和访问,对于更复杂的应用程序,它非常有用。

你可以在这里找到包:https://pub.dev/packages/flutter_bloc#-readme-tab-

写信:https://www.didierboelens.com/2018/08/reactive-programming-streams-bloc/

还有一个很棒的 youtube 教程https://www.youtube.com/watch?v=hTExlt1nJZI&list=PLB6lc7nQ1n4jCBkrirvVGr5b8rC95VAQ5&index=7

【讨论】:

【参考方案2】:

尽可能避免这种情况。它使这些小部件相互依赖,并且从长远来看会使事情变得更难维护。

您可以做的是让两个小部件共享一个共同的Listenable 或类似的东西,例如Stream。然后小部件通过提交事件相互交互。

为了更容易编写,您还可以将Listenable/Stream 分别与ValueListenableBuilderStreamBuilder 组合在一起,它们都为您完成了监听/更新部分。

Listenable 的简单示例。

class MyHomePage extends StatelessWidget 
  final number = new ValueNotifier(0);

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: ValueListenableBuilder<int>(
        valueListenable: number,
        builder: (context, value, child) 
          return Center(
            child: RaisedButton(
              onPressed: () 
                number.value++;
              ,
              child: MyWidget(number),
            ),
          );
        ,
      ),
    );
  


class MyWidget extends StatelessWidget 
  final ValueListenable<int> number;

  MyWidget(this.number);

  @override
  Widget build(BuildContext context) 
    return new Text(number.value.toString());
  

请注意,我们如何在执行number.value++ 时自动更新 UI,而无需调用 setState

【讨论】:

这看起来很有希望。我会在早上的第一件事上测试它!但我没有完全理解的一件事是 Flutter 如何知道重新渲染小部件。你能解释一下那部分吗? AnimatedWidget/StreamBuilder 实际上包含重新渲染逻辑。它们都监听各自的对象,并在收到更改通知时调用 setstate,其中再次调用 builder 其背后的技巧是,在我的示例中,MyHomePage 实际上并没有更新。这是AnimatedWidget 啊哈,这就解释了! @BramVanbilsen 如果您在小部件中嵌套了很多东西,而不是让ValueListenableBuilder 每次都重建所有内容,您应该查看child 参数,并使用它来显着优化渲染.阅读更多:docs.flutter.io/flutter/widgets/…

以上是关于如何从另一个小部件设置状态?的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个小部件状态处理一个小部件状态?

如何从另一个小部件类更新小部件树 - Flutter

如何从另一个 dart 文件中调用有状态小部件(有表单)方法?- Flutter

从另一个小部件更改一个小部件中的状态

从另一个有状态小部件调用一个有状态小部件中的方法 - Flutter

如何在从另一个小部件继承的小部件中设置数据?