@@ -128,7 +128,7 @@ class _MyHomePageState extends State<MyHomePage> {
128128
129129 - ` MyApp ` 类代表Flutter应用,它继承了 ` StatelessWidget ` 类,这也就意味着应用本身也是一个widget。
130130
131- - 在Flutter中,大多数东西都是widget(后同”组件“或”部件“ ),包括对齐(alignment)、填充(padding)和布局(layout)等,它们都是以widget的形式提供。
131+ - 在Flutter中,大多数东西都是widget(后同“组件”或“部件” ),包括对齐(alignment)、填充(padding)和布局(layout)等,它们都是以widget的形式提供。
132132
133133 - Flutter在构建页面时,会调用组件的` build ` 方法,widget的主要工作是提供一个build()方法来描述如何构建UI界面(通常是通过组合、拼装其它基础widget)。
134134
@@ -153,7 +153,7 @@ class _MyHomePageState extends State<MyHomePage> {
153153 }
154154 ```
155155
156- ` MyHomePage ` 是Flutter应用的首页,它继承自` StatefulWidget ` 类,表示它是一个有状态的组件(Stateful widget)。关于Stateful widget我们将在第三章”Widget简介“一节自习介绍 ,现在我们只需简单认为有状态的组件(Stateful widget) 和无状态的组件(Stateless widget)有两点不同:
156+ ` MyHomePage ` 是Flutter应用的首页,它继承自` StatefulWidget ` 类,表示它是一个有状态的组件(Stateful widget)。关于Stateful widget我们将在第三章“Widget简介”一节仔细介绍 ,现在我们只需简单认为有状态的组件(Stateful widget) 和无状态的组件(Stateless widget)有两点不同:
157157
1581581 . Stateful widget可以拥有状态,这些状态在widget生命周期中是可以变的,而Stateless widget是不可变的。
159159
@@ -220,12 +220,52 @@ class _MyHomePageState extends State<MyHomePage> {
220220 }
221221 ```
222222
223- - ` Scaffold ` 是 Material组件库中提供的一个组件,它提供了默认的导航栏、标题和包含主屏幕widget树(后同”组件树“或”部件树“ )的` body ` 属性。组件树可以很复杂。
223+ - ` Scaffold ` 是 Material组件库中提供的一个组件,它提供了默认的导航栏、标题和包含主屏幕widget树(后同“组件树”或“部件树” )的` body ` 属性。组件树可以很复杂。
224224 - ` body ` 的组件树中包含了一个` Center ` 组件,` Center ` 可以将其子组件树对齐到屏幕中心。此例中, ` Center ` 子组件是一个` Column ` 组件,` Column ` 的作用是将其所有子组件沿屏幕垂直方向依次排列; 此例中` Column ` 子组件是两个 ` Text ` ,第一个` Text ` 显示固定文本 “You have pushed the button this many times:”,第二个` Text ` 显示` _counter ` 状态的数值。
225225 - ` floatingActionButton ` 是页面右下角的带“+”的悬浮按钮,它的` onPressed ` 属性接受一个回调函数,代表它被点击后的处理器,本例中直接将` _incrementCounter ` 方法作为其处理函数。
226226
227227
228+
228229现在,我们将整个计数器执行流程串起来:当右下角的` floatingActionButton ` 按钮被点击之后,会调用` _incrementCounter ` 方法。在` _incrementCounter ` 方法中,首先会自增` _counter ` 计数器(状态),然后` setState ` 会通知Flutter框架状态发生变化,接着,Flutter框架会调用` build ` 方法以新的状态重新构建UI,最终显示在设备屏幕上。
229230
230231
232+ #### 为什么要将build方法放在State中,而不是放在StatefulWidget中?
233+
234+ 现在,我们回答之前提出的问题,为什么` build() ` 方法放在State(而不是` StatefulWidget ` )中 ?这主要是为了提高开发的灵活性。如果将` build() ` 方法放在` StatefulWidget ` 中则会有两个问题:
235+
236+ - 状态访问不便
237+
238+ 试想一下,如果我们的` StatefulWidget ` 有很多状态,而每次状态改变都要调用` build ` 方法,由于状态是保存在State中的,如果` build ` 方法在` StatefulWidget ` 中,那么` build ` 方法和状态分别在两个类中,那么构建时读取状态将会很不方便!试想一下,如果真的将` build ` 方法放在StatefulWidget中的话,由于构建用户界面过程需要依赖State,所以` build ` 方法将必须加一个` State ` 参数,大概是下面这样:
239+
240+ ``` dart
241+ Widget build(BuildContext context, State state){
242+ //state.counter
243+ ...
244+ }
245+ ```
246+
247+ 这样的话就只能将State的所有状态声明为公开的状态,这样才能在State类外部访问状态!但是,将状态设置为公开后,状态将不再具有私密性,这就会导致对状态的修改将会变的不可控。但如果将` build() ` 方法放在State中的话,构建过程不仅可以直接访问状态,而且也无需公开私有状态,这会非常方便。
248+
249+ - 继承` StatefulWidget ` 不便
250+
251+ 例如,Flutter中有一个动画widget的基类` AnimatedWidget ` ,它继承自` StatefulWidget ` 类。` AnimatedWidget ` 中引入了一个抽象方法` build(BuildContext context) ` ,继承自` AnimatedWidget ` 的动画widget都要实现这个` build ` 方法。现在设想一下,如果` StatefulWidget ` 类中已经有了一个` build ` 方法,正如上面所述,此时` build ` 方法需要接收一个state对象,这就意味着` AnimatedWidget ` 必须将自己的State对象(记为_animatedWidgetState)提供给其子类,因为子类需要在其` build ` 方法中调用父类的` build ` 方法,代码可能如下:
252+
253+ ``` dart
254+ class MyAnimationWidget extends AnimatedWidget{
255+ @override
256+ Widget build(BuildContext context, State state){
257+ //由于子类要用到AnimatedWidget的状态对象_animatedWidgetState,
258+ //所以AnimatedWidget必须通过某种方式将其状态对象_animatedWidgetState
259+ //暴露给其子类
260+ super.build(context, _animatedWidgetState)
261+ }
262+ }
263+ ```
264+
265+ 这样很显然是不合理的,因为
266+
267+ 1 . ` AnimatedWidget ` 的状态对象是` AnimatedWidget ` 内部实现细节,不应该暴露给外部。
268+ 2 . 如果要将父类状态暴露给子类,那么必须得有一种传递机制,而做这一套传递机制是无意义的,因为父子类之间状态的传递和子类本身逻辑是无关的。
269+
270+ 综上所述,可以发现,对于` StatefulWidget ` ,将` build ` 方法放在State中,可以给开发带来很大的灵活性。
231271
0 commit comments