Flutter之Widget和Element关系浅析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chunqiuwei/article/details/87855312

Flutter的Widget分为StatelessWidget和StatefulWidget两种,二者的的使用方式大致模板代码如下:

//StatelessWidget的使用模板代码
class StatelessWidgetDemo extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return null;///返回创建的页面
  }
}


//StatefulWidget的使用方式模板代码
class StatefulWidgetDemo extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    //创建state对象
    return _State();
  }
}
class _State extends State<StatefulWidgetDemo>{
  //创建页面
  @override
  Widget build(BuildContext context) {
    return null;
  }
}

这是典型的模板设计模式的应用,我们只需要依葫芦画瓢就可以创建所需的UI页面。本篇博文主要来讲讲Widget的一些基本知识。
阅读上面的代码,可以跑出一下问题:
1) build方法需要一个BuildContext参数,那么这个BuildContext是什么?
2)build方法是末班方法,那么什么时候调用的呢?
带着这两个问题,后面简单的梳理下Widget的结构,之所以说是简单的梳理,因为难得我也不会,还没研究到。

StatelessWidget和StatefulWidget都继承于Widget,其定义如下:

abstract class Widget extends DiagnosticableTree {
  const Widget({ this.key });
  final Key key;
  @protected
  Element createElement();
}

Widget继承于DiagnosticableTree,且提供了一个createElement抽象方法返回了一个Element对象,该对象查看源码可知其继承解构是Element extends DiagnosticableTree implements BuildContext.所以其Widget 和Element的整体解构可以用如下图表示:
在这里插入图片描述

先来看看StatelessWidget的具体实现:

abstract class StatelessWidget extends Widget {

 @override
  StatelessElement createElement() => StatelessElement(this);
  
  @protected
  Widget build(BuildContext context);
}

StatelessWidget实现了createElement方法返回了一个StatelessElement对象,且提供了一个build方法,注意build方法的参数是BuildContext,那么这个BuildContext是不是就是StatelessElement这个对象了呢?预知答案如何先看看build是在那儿调用的,在StatelessElement这个类里可以找到答案,其源码如下:

class StatelessElement extends ComponentElement {
  //在element中调用了widget.build方法,并将自己传入了进去
  //所以BuildContext就是StatelessElement
  @override
  Widget build() => widget.build(this);
}

通过其源码可以知道StatelessElement继承了ComponentElement,且重写了build方法,其调用了widget的build方法。这个build就是StatelessWidget对象(或者其子对象),并且可以确定StatelessWidget的build方法的参数就是StatelessElement这个对象。

所以可以断定想要知道StatelessWidget的build(BuildContext)方法什么时候调用,就需要知道StatelessElement的build()什么时候调用。在StatelessElement的父类ComponentElement的perfromReBuild方法可以得到解答:


@override
  void performRebuild() {
   //省略了部分代码
    Widget  built = build();

    //省略部分代码
  }

所以概述下来就是StatelessWidget通过build(BuildContext)方法构建Widget是通过StatelessElement的build()方法来完成的。想要调用build(BuildContext)必定先通过createElement方法创建一个StatelessElement对象。那么有一个此处就有一个问题了,本问题博主还没有暂时挖掘出来答案:Widget的createElement方法是神马时候调用的呢


上面粗略的分了StatelessWidget,下来再来简略的看下StatefullWidget这个类。

 abstract class StatefulWidget extends Widget {
 
  @override
  StatefulElement createElement() => StatefulElement(this);

  @protected
  State createState();
}

StatefulWidget的createElement方法返回了SatefulElement,且提供了一个createState()方法,大胆猜测一下createState就是在StatefulElement里面调用的,果不其然,证据如下:

 StatefulElement 的构造器:
   StatefulElement(StatefulWidget widget)
    ///调用了createState方法
    : _state = widget.createState(), super(widget) {
   
  }

文章开头的代码说明了StatefulWidget需要通过createState方法创建一个State,State也提供了build(BuildContext)方法。另外查看StatefulElement的可以该类也实现了ComponentElement的build方法:

  @override
  Widget build() => state.build(this);

分析到这儿Widget和Element的关系可以用如下图来表示:
在这里插入图片描述
其构建关系的流程图可以用如下来表示:
在这里插入图片描述

到此为止,本篇博文就此结束。我们知道了想要调用build(BuildContext)方法就需要先调用具体子类的createElement方法创建对应的ComponentElement对象,而后重写Component的build方法。本篇博文没有讲到的问题有两个:
1)Widget的createElement是神马时候调用的
2)performRebuild方法又是什么时机调用的
这两个问题博主暂时还没有分析到,且听下回分解吧。

猜你喜欢

转载自blog.csdn.net/chunqiuwei/article/details/87855312