美文网首页
statelessWidget和statefulWidget简介

statelessWidget和statefulWidget简介

作者: lovefo | 来源:发表于2019-06-12 10:15 被阅读0次

    statelessWidget

    StatelessWidget用于不需要维护状态的场景,它通常在build方法中通过嵌套其它Widget来构建UI,在构建过程中会递归的构建其嵌套的Widget

    class Echo extends StatelessWidget {
      const Echo({
        Key key,  
        @required this.text,
        this.backgroundColor:Colors.grey,
      }):super(key:key);
    
      final String text;
      final Color backgroundColor;
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Container(
            color: backgroundColor,
            child: Text(text),
          ),
        );
      }
    }
    

    上面的代码,实现了一个回显字符串的Echo widget。
    然后我们可以通过如下方式使用它:

    Widget build(BuildContext context) {
      return Echo(text: "hello world");
    }
    

    statefulWidget

    和StatelessWidget一样,StatefulWidget也是继承自widget类,并重写了createElement()方法,不同的是返回的Element 对象并不相同;另外StatefulWidget类中添加了一个新的接口createState().

    • StatefulElement 间接继承自Element类,与StatefulWidget相对应(作为其配置数据)。StatefulElement中可能会多次调用createState()来创建状态(State)对象。
    • createState() 用于创建和Stateful widget相关的状态,它在Stateful widget的生命周期中可能会被多次调用。例如,当一个Stateful widget同时插入到widget树的多个位置时,Flutter framework就会调用该方法为每一个位置生成一个独立的State实例,其实,本质上就是一个StatefulElement对应一个State实例

    State

    一个StatefulWidget类会对应一个State类,State表示与其对应的StatefulWidget要维护的状态,State中的保存的状态信息可以:

    1. 在widget build时可以被同步读取。
    2. 在widget生命周期中可以被改变,当State被改变时,可以手动调用其setState()方法通知Flutter framework状态发生改变,Flutter framework在收到消息后,会重新调用其build方法重新构建widget树,从而达到更新UI的目的.

    State中有两个常用属性

    1. widget,它表示与该State实例关联的widget实例,由Flutter framework动态设置。注意,这种关联并非永久的,因为在应用声明周期中,UI树上的某一个节点的widget实例在重新构建时可能会变化,但State实例只会在第一次插入到树中时被创建,当在重新构建时,如果widget被修改了,Flutter framework会动态设置State.widget为新的widget实例。
    2. context,它是BuildContext类的一个实例,表示构建widget的上下文,它是操作widget在树中位置的一个句柄,它包含了一些查找、遍历当前Widget树的一些方法。每一个widget都有一个自己的context对象。

    State生命周期

    class _CounterWidgetState extends State<CounterWidget> {  
      int _counter;
    
      @override
      void initState() {
        super.initState();
        //初始化状态  
        _counter=widget.initValue;
        print("initState");
      }
    
      @override
      Widget build(BuildContext context) {
        print("build");
        return Scaffold(
          body: Center(
            child: FlatButton(
              child: Text('$_counter'),
              //点击后计数器自增
              onPressed:()=>setState(()=> ++_counter,
              ),
            ),
          ),
        );
      }
    
      @override
      void didUpdateWidget(CounterWidget oldWidget) {
        super.didUpdateWidget(oldWidget);
        print("didUpdateWidget");
      }
    
      @override
      void deactivate() {
        super.deactivate();
        print("deactive");
      }
    
      @override
      void dispose() {
        super.dispose();
        print("dispose");
      }
    
      @override
      void reassemble() {
        super.reassemble();
        print("reassemble");
      }
    
      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        print("didChangeDependencies");
      }
    }
    

    函数解析

    • initState:当Widget第一次插入到Widget树时会被调用,对于每一个State对象,Flutter framework只会调用一次该回调,所以,通常在该回调中做一些一次性的操作,如状态初始化、订阅子树的事件通知等。不能在该回调中调用BuildContext.inheritFromWidgetOfExactType(该方法用于在Widget树上获取离当前widget最近的一个父级InheritFromWidget,关于InheritedWidget我们将在后面章节介绍),原因是在初始化完成后,Widget树中的InheritFromWidget也可能会发生变化,所以正确的做法应该在在build()方法或didChangeDependencies()中调用它。

    • didChangeDependencies():当State对象的依赖发生变化时会被调用;例如:在之前build() 中包含了一个InheritedWidget,然后在之后的build() 中InheritedWidget发生了变化,那么此时InheritedWidget的子widget的didChangeDependencies()回调都会被调用。典型的场景是当系统语言Locale或应用主题改变时,Flutter framework会通知widget调用此回调

    • build():此回调读者现在应该已经相当熟悉了,它主要是用于构建Widget子树的,会在如下场景被调用:
      1.在调用initState()之后。
      2.在调用didUpdateWidget()之后。
      3.在调用setState()之后。
      4.在调用didChangeDependencies()之后。
      5.在State对象从树中一个位置移除后(会调用deactivate)又重新插入到树的其它位置之后。

    • reassemble():此回调是专门为了开发调试而提供的,在热重载(hot reload)时会被调用,此回调在Release模式下永远不会被调用。

    • didUpdateWidget():在widget重新构建时,Flutter framework会调用Widget.canUpdate来检测Widget树中同一位置的新旧节点,然后决定是否需要更新,如果Widget.canUpdate返回true则会调用此回调。正如之前所述,Widget.canUpdate会在新旧widget的key和runtimeType同时相等时会返回true,也就是说在在新旧widget的key和runtimeType同时相等时didUpdateWidget()就会被调用。

    • deactivate():当State对象从树中被移除时,会调用此回调。在一些场景下,Flutter framework会将State对象重新插到树中,如包含此State对象的子树在树的一个位置移动到另一个位置时(可以通过GlobalKey来实现)。如果移除后没有重新插入到树中则紧接着会调用dispose()方法。

    • dispose():当State对象从树中被永久移除时调用;通常在此回调中释放资源。

    相关文章

      网友评论

          本文标题:statelessWidget和statefulWidget简介

          本文链接:https://www.haomeiwen.com/subject/rukkfctx.html