如何从另一个小部件设置状态?
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
分别与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());
请注意,我们如何在执行number.value++
时自动更新 UI,而无需调用 setState
。
【讨论】:
这看起来很有希望。我会在早上的第一件事上测试它!但我没有完全理解的一件事是 Flutter 如何知道重新渲染小部件。你能解释一下那部分吗?AnimatedWidget
/StreamBuilder
实际上包含重新渲染逻辑。它们都监听各自的对象,并在收到更改通知时调用 setstate
,其中再次调用 builder
。
其背后的技巧是,在我的示例中,MyHomePage
实际上并没有更新。这是AnimatedWidget
。
啊哈,这就解释了!
@BramVanbilsen 如果您在小部件中嵌套了很多东西,而不是让ValueListenableBuilder
每次都重建所有内容,您应该查看child
参数,并使用它来显着优化渲染.阅读更多:docs.flutter.io/flutter/widgets/…以上是关于如何从另一个小部件设置状态?的主要内容,如果未能解决你的问题,请参考以下文章
如何从另一个 dart 文件中调用有状态小部件(有表单)方法?- Flutter