我正在尝试从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,但是除非将其包装在顶层窗口小部件上,否则将无法正常工作,这对于我要执行的操作不可行(上面的代码是我要实现的功能的简化)。
InheritedWidget
关于实现此目标的最佳方法的任何想法是在Flutter中吗?
尽可能避免这种情况。这使得这些小部件彼此依赖,并且从长远来看会使事情变得更难维护。
相反,您可以做的是让两个小部件共享一个公共Listenable或类似的名称,例如Stream。然后,小部件通过提交事件进行交互。
Listenable
Stream
为了更容易编写,您还可以将Listenable/ Stream与分别组合,ValueListenableBuilder并且StreamBuilder两者都可以为您提供监听/更新部分。
ValueListenableBuilder
StreamBuilder
一个简单的例子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()); } }
请注意这里,我们如何在执行操作时自动更新UI,number.value++而无需调用setState。
number.value++
setState