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

Dart 如何从另一个小部件设置状态?,dart,flutter,Dart,Flutter,我正在尝试从flifter中的另一个小部件更改状态。例如,在下面的示例中,我在几秒钟后设置了状态 以下是代码: class _MyAppState extends State<MyApp> { int number = 1; @override void initState() { super.initState(); new Future.delayed(new Duration(seconds: 5)).then((_) { this.

我正在尝试从flifter中的另一个小部件更改状态。例如,在下面的示例中,我在几秒钟后设置了状态

以下是代码:

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))
            ));
          },
        ),
      ),
    );
  }
}
class\u MyAppState扩展状态{
整数=1;
@凌驾
void initState(){
super.initState();
新的未来。延迟(新的持续时间(秒:5))。然后((){
此.setState(()=>number=2);
打印(“更改”);
});
}
@凌驾
小部件构建(构建上下文){
归还新脚手架(
正文:新中心(
孩子:新的扁平按钮(
颜色:颜色,蓝色,
子项:新文本(“下一页”),
已按下:(){
导航器.of(上下文).push(新材料路线)(
builder:(BuildContext context)=>newstatefulbuilder(builder:(BuildContext context,setState)=>newmysecondpage(number))
));
},
),
),
);
}
}
我尝试使用一个
InheritedWidget
,但除非我将它包装在我的顶级widget上,否则它不会起作用,这对于我尝试做的事情来说是不可行的(上面的代码是我试图实现的简化)


关于在颤振中实现这一点的最佳方法有什么想法吗?

尽可能避免这种情况。它使这些小部件相互依赖,并使长期维护变得更加困难

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

为了便于编写,您还可以将
Listenable
/
Stream
分别与和组合起来,两者都为您执行侦听/更新部分

使用
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());
  }
}
class MyHomePage扩展了无状态小部件{
最终编号=新的ValueNotifier(0);
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:ValueListenableBuilder(
valueListenable:number,
生成器:(上下文、值、子级){
返回中心(
孩子:升起按钮(
已按下:(){
数值++;
},
子项:MyWidget(编号),
),
);
},
),
);
}
}
类MyWidget扩展了无状态Widget{
最终值可输入的数字;
MyWidget(this.number);
@凌驾
小部件构建(构建上下文){
返回新文本(number.value.toString());
}
}

请注意,在执行
number.value++
操作时,用户界面是如何自动更新的,而无需调用
setState

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

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());
  }
}
您可以在此处找到软件包:

撰写:


youtube上有一个很棒的教程,看起来很有希望。我明天早上第一件事就是测试它!但有一件事我没有完全理解,那就是flifter如何重新呈现这个小部件。你能解释一下这一部分吗?这是
动画小部件
/
流生成器
,它实际上包含了重新渲染逻辑。他们都会监听各自的对象,并在收到更改通知时调用
setstate
,其中
builder
再次被调用。其背后的技巧是,在我的示例中,
MyHomePage
实际上没有更新。是
AnimatedWidget
做的。啊哈,这就解释了@BramVanbilsen如果小部件中嵌套了大量内容,而不是每次都让
ValueListenableBuilder
重新生成所有内容,那么您应该查看
参数,并使用该参数显著优化渲染。阅读更多:相似,如果不一样:)@giorgio79这个问题在你链接的问题之前被问过?