iOS 开发相关

Flutter_定义控件StatefulWidgets和Stat

2019-03-21  本文已影响33人  icechao

Stateful(有状态) 和 stateless(无状态) widgets

    什么是重点?
    
    有些widgets是有状态的, 有些是无状态的
    
    如果用户与widget交互,widget会发生变化,那么它就是有状态的.
    
    widget的状态(state)是一些可以更改的值, 如一个slider滑动条的当前值或checkbox是否被选中.
    
    widget的状态保存在一个State对象中, 它和widget的布局显示分离。
    
    当widget状态改变时, State 对象调用setState(), 告诉框架去重绘widget.

stateless widget 没有内部状态. Icon、 IconButton, 和Text 都是无状态widget, 他们都是 StatelessWidget的子类。

stateful widget 是动态的. 用户可以和其交互 (例如输入一个表单、 或者移动一个slider滑块),或者可以随时间改变 (也许是数据改变导致的UI更新). Checkbox, Radio, Slider, InkWell, Form, and TextField 都是 stateful widgets, 他们都是 StatefulWidget的子类。

重点:
要创建一个自定义有状态widget,需创建两个类:StatefulWidget和State
状态对象包含widget的状态和build() 方法。
当widget的状态改变时,状态对象调用setState(),告诉框架重绘widget

StatefulWidget类
具有可变状态的小部件。

状态是(1)在构建窗口小部件时可以同步读取的信息,以及(2)在窗口小部件的生命周期内可能会更改的信息。这是小工具实施者的责任,以确保国家的及时通知当这种状态的改变,使用State.setState。

有状态窗口小部件是一个窗口小部件,它通过构建一个更具体地描述用户界面的其他窗口小部件来描述用户界面的一部分。构建过程以递归方式继续,直到用户界面的描述完全具体(例如,完全由RenderObjectWidget组成,其描述具体的RenderObject)。

当您描述的用户界面部分可以动态更改时(例如由于具有内部时钟驱动状态或依赖于某些系统状态),状态窗口小部件非常有用。对于仅依赖于对象本身中的配置信息以及窗口小部件膨胀的 BuildContext的组合,请考虑使用 StatelessWidget。

StatefulWidget实例本身是不可变的,并且将它们的可变状态存储在由createState方法创建的单独State对象中 ,或者存储在State订阅的对象中,例如Stream或ChangeNotifier对象,其引用存储在StatefulWidget的最终字段中本身。

框架在膨胀StatefulWidget时 调用createState,这意味着如果该窗口小部件已插入到多个位置的树中,则多个State对象可能与同一StatefulWidget关联。同样,如果StatefulWidget从树中移除,后来在树再次插入时,框架将调用createState再创建一个新的国家目标,简化的生命周期状态的对象。

如果StatefulWidget的创建者使用GlobalKey作为其 键,则StatefulWidget在从树中的一个位置移动到另一个位置时保持相同的State对象。由于具有GlobalKey的窗口小部件可以在树中的至多一个位置使用,因此使用GlobalKey的窗口小部件最多只有一个关联元素。当通过将与该窗口小部件关联的(唯一)子树从旧位置移植到新位置(而不是在该位置重新创建子树)时,框架利用此属性将全局键从树中的一个位置移动到另一个位置时利用此属性。新的位置)。与StatefulWidget关联的State对象与子树的其余部分一起被移植,这意味着State对象在新位置被重用(而不是被重新创建)。但是,为了有资格进行嫁接,必须将窗口小部件插入到从旧位置移除它的同一动画帧中的新位置。

性能考虑因素

StatefulWidget有两个主要类别。

首先是其中一个分配资源State.initState并在他们的处置State.dispose,但不依赖于InheritedWidget S或致电State.setState。这些小部件通常在应用程序或页面的根目录中使用,并通过ChangeNotifier, Stream或其他此类对象与子小部件进行通信。遵循这种模式的有状态小部件相对便宜(就CPU和GPU周期而言),因为它们构建一次然后永不更新。因此,它们可能有一些复杂和深刻的构建方法。

第二类是使用State.setState或依赖于 InheritedWidget的小部件。这些通常会在应用程序的生命周期内重建多次,因此最小化重建此类窗口小部件的影响非常重要。(他们也可以使用State.initState或 State.didChangeDependencies并分配资源,但重要的是他们重建。)

可以使用几种技术来最小化重建有状态窗口小部件的影响:

实现一个自定义的有状态widget需要创建两个类:
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            //        title: 'Flutter Code Sample for material.Scaffold',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: FavoriteWidget());
      }
    }
    1. 定义一个widget类,继承自StatefulWidget.
    class FavoriteWidget extends StatefulWidget {
      @override
      _FavoriteWidgetState createState() => new _FavoriteWidgetState();
    }
    
    2. 包含该widget状态并定义该widget build()方法的类,它继承自State.
    class _FavoriteWidgetState extends State<FavoriteWidget> {
      bool _isFavorited = true;
      int _favoriteCount = 41;
    
      void _toggleFavorite() {
        setState(() {
          // If the lake is currently favorited, unfavorite it.
          if (_isFavorited) {
            _favoriteCount -= 1;
            _isFavorited = false;
            // Otherwise, favorite it.
          } else {
            _favoriteCount += 1;
            _isFavorited = true;
          }
        });
      }
    
      @override
      Widget build(BuildContext context) {
        Widget content = Row(
          mainAxisSize: MainAxisSize.min,
          textDirection: TextDirection.ltr,
          children: [
            new Container(
              padding: new EdgeInsets.all(0.0),
              child: Center(
                child : IconButton(
                  icon: (_isFavorited
                      ? new Icon(Icons.star, textDirection: TextDirection.ltr)
                      : new Icon(Icons.star_border,
                          textDirection: TextDirection.ltr)),
                  color: Colors.red[500],
                  onPressed: _toggleFavorite,
                ),
              ),
            ),
            new SizedBox(
              width: 18.0,
              child: new Container(
                child: new Text(
                  '$_favoriteCount',
                  textDirection: TextDirection.ltr,
                ),
              ),
            ),
          ],
        );
        return Scaffold(body: content);
      }
}
IconButtonb必须要有一个Material Design的父类才能生效不然会报错

StatelessWidget类
一个不需要可变状态的小部件。

无状态窗口小部件是一个窗口小部件,它通过构建一个更具体地描述用户界面的其他窗口小部件来描述用户界面的一部分。构建过程以递归方式继续,直到用户界面的描述完全具体(例如,完全由RenderObjectWidget组成,其描述具体的RenderObject)。

当您描述的用户界面部分不依赖于对象本身的配置信息以及窗口小部件膨胀的BuildContext时,无状态窗口小部件非常有用。对于可以动态更改的组合,例如由于具有内部时钟驱动状态或依赖于某些系统状态,请考虑使用StatefulWidget。

性能考虑因素

无状态窗口小部件的构建方法通常仅在以下三种情况下调用:第一次将窗口小部件插入树中,窗口小部件的父窗口更改其配置时,以及何时依赖于更改的InheritedWidget。

如果窗口小部件的父级将定期更改窗口小部件的配置,或者它依赖于经常更改的继承窗口小部件,则优化构建方法的性能以保持流畅的呈现性能非常重要。

可以使用几种技术来最小化重建无状态窗口小部件的影响:

上一篇 下一篇

猜你喜欢

热点阅读