[英]How does the stateful vs. stateless distinction affect when widgets will be rebuilt?
I am trying to understand how state and lifting state works in Flutter.我想了解状态和提升状态在 Flutter 中是如何工作的。 In the code below I made a simple app where I tried to pass or lift a string and a function through multiple levels.
在下面的代码中,我制作了一个简单的应用程序,我试图通过多个级别传递或提升一个字符串和一个函数。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String data = 'MyApp class data';
void setTextField(String s) {
setState(
() {
data = s;
},
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainApp(data, setTextField),
);
}
}
class MainApp extends StatelessWidget {
final String mainAppData;
final Function setTextField;
MainApp(this.mainAppData, this.setTextField);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(mainAppData)),
body: Container(
child: Level2(mainAppData, setTextField),
),
);
}
}
class Level2 extends StatelessWidget {
final String level2Data;
final Function setTextField;
Level2(this.level2Data, this.setTextField);
@override
Widget build(BuildContext context) {
return Container(
child: Level3(level2Data, setTextField),
);
}
}
class Level3 extends StatefulWidget {
final String level3Data;
final Function setTextField;
Level3(this.level3Data, this.setTextField);
@override
_Level3State createState() {
print('Level3: $this.level3Data');
return _Level3State(this.level3Data, this.setTextField);
}
}
class _Level3State extends State<Level3> {
String level3Data;
Function setTextField;
_Level3State(this.level3Data, this.setTextField);
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
TextField(
onChanged: setTextField,
),
Text(level3Data),
],
);
}
}
When the app starts, the string data
in the _MyAppState
state class is passed to the MainApp
StatelessWidget when MainApp
is built.当应用程序启动时,
_MyAppState
状态类中的字符串data
会在构建MainApp
时传递给MainApp
StatelessWidget。 In a similar manner, info is passed then to Level2
StatelessWidget and Level3
StatefulWidget.然后以类似的方式将信息传递给
Level2
StatelessWidget 和Level3
StatefulWidget。
When the TextField
in Level3
changes, setTextField
is triggered.当
Level3
中的TextField
发生变化时,触发setTextField
。 setTextField
is defined up in MyApp
and I figured that when the String data
changes (inside setState()
) it should trigger rebuilding of all the widgets affected by the change. setTextField
是在MyApp
中定义的,我认为当 String data
发生变化时(在setState()
内部)它应该触发重建所有受变化影响的小部件。
The text in the MainApp
widget (appBar) changes, showing MainApp
was rebuilt as I expected. MainApp
小部件 (appBar) 中的文本发生变化,显示MainApp
已按预期重建。 But nothing happens to the Level3
widget;但是
Level3
小部件没有任何反应; it's not rebuilt.它没有重建。 The print statement in the
createState()
method does not execute, and the Text widget's text does not change. createState()
方法中的 print 语句不执行,Text 小部件的文本不改变。
Why doesn't the Level3
StatefulWidget rebuild?为什么
Level3
StatefulWidget 不重建?
In my understanding, the stateful widget Level3 is already created at the given location in the tree.据我所知,有状态的小部件 Level3 已经在树中的给定位置创建。 And according to the contract of the stateful widget , It is the responsibility of the widget implementer to ensure that the State is promptly notified when such state changes, using State.setState.
并且根据有状态小部件的契约,小部件实现者有责任确保在此类状态更改时及时通知 State,使用 State.setState。 So in your case you need to have setstate in level3 to be notified of the change again.
因此,在您的情况下,您需要在 level3 中设置 setstate 才能再次收到更改通知。 The rebuilding only happens at level 1 because setState is called.
重建只发生在级别 1,因为调用了 setState。
The rebuilding process continues recursively until the description of the user interface is fully concrete.重建过程递归地继续,直到用户界面的描述完全具体。 In Level 3, the class has its own set of fields String level3Data;
在级别 3 中,该类有自己的一组字段 String level3Data; Function setTextField;
函数设置文本字段; It means these need to be again set using SetState or if you do something like this then the widget building continues.
这意味着这些需要使用 SetState 再次设置,或者如果您执行类似的操作,则小部件构建将继续。
class Level3 extends StatefulWidget {
final String level3Data;
final Function setTextField;
Level3(this.level3Data, this.setTextField);
@override
_Level3State createState() {
print('Level3: $this.level3Data');
return _Level3State();
}
}
class _Level3State extends State<Level3> {
// String level3Data;
// Function setTextField;
@override
Widget build(BuildContext _) {
return Column(
children: <Widget>[
TextField(
onChanged: widget.setTextField,
),
Text(widget.level3Data),
],
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.