美文网首页
Flutter: WidgetTree、ElementTree

Flutter: WidgetTree、ElementTree

作者: 狂奔的胖蜗牛 | 来源:发表于2021-03-23 00:43 被阅读0次

1.简介

我们知道,Flutter的页面是由很多个Widget组成的,或许你已经知道怎么写页面了,但是你有没有好奇,多个Widget是怎么实现组合成一个页面的呢?

2.StatelessWidget组成的页面

首先我们看看StatelessWidget的源码:

abstract class StatelessWidget extends Widget {
  const StatelessWidget({ Key key }) : super(key: key);

  @override
  StatelessElement createElement() => StatelessElement(this);

  @protected
  Widget build(BuildContext context);
}

请先注意createElementbuild方法。

我们先从一个简单的由StatelessWidget组成的页面开始。

void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return First();
  }
}
class First extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

在上面的代码中,Flutter通过Widget build(BuildContext context);方法创建出了一个WidgetTree,内容如下:

image.png
在Flutter中,Widget Tree只是界面的蓝图,只是代表了界面上有哪些Widget,并没有包含每个Widget的展示信息。

那么,我们的界面是怎么显示出来的呢?通过Element Tree来决定如何展示界面。在Flutter中,每个Widget都会有一个对应的元素类。Flutter会通过StatelessElement createElement() => StatelessElement(this);这个方法,创建出Widget的Element元素。当Widget被创建时,会调用该方法创建出元素类,同时挂载到Element Tree上面。我们上面的代码,就会创建出下面的Element Tree。

image.png
显示的时候,Flutter会去Element Tree查询到Widget对应的Element然后显示。
image.png
通过Widget Tree和Element Tree,Flutter就能决定界面是如何显示的了。但是,我们是用的StatelessWidget构建的页面是无状态的,界面不会跟着数据的变化而变化。所以此时,我们需要使用StatefulWidget。

3.StatefulWidget组成的页面

先看看StatefulWidget的源码:

abstract class StatefulWidget extends Widget {
  const StatefulWidget({ Key key }) : super(key: key);

  @override
  StatefulElement createElement() => StatefulElement(this);

  @protected
  @factory
  State createState();
}

可以看到createElement返回了StatefulElement这个元素类。

进入StatefulElement源码中,注意看红框圈起来的内容。

image
是不是似曾相识?是的,你没有看错,就是StatefulWidget里面的State createState();方法。这样,通过StatelessWidget构建Widget Tree和Element Tree的流程,我们就能联系起来了。
  • 当创建一个StatefulWidget时,依然会有Widget Tree和Element Tree,只是此时,Element Tree里面是StatefulElement元素类。
  • 同时,创建StatefulElement元素类时,StatefulElement会调用StatefulWidget的createState获得StatefulWidget的State类,并且保持下来。
  • 构建Widget Tree时,会通过调用State的build方法来构建。
  • 在State内使用setState方法,能够触发界面的更新。Flutter会根据Element保持的State去刷新Widget。


    image.png

这就是StatefulWidget构建页面的过程。我们接下来看看StatefulWidget界面刷新的流程是什么样子的。

4.StatefulWidget界面刷新

先沿用上面的图,当界面构建完成后,如图所示:


image.png

然后,当我们State里面的属性有变化后,State会被Flutter标记。


image.png
此时,我们调用setState方法,触发界面的更新,Flutter会发现State被标记了,那么,他就会创建出一个新的Text。
image.png

然后将原来的Text删除,把新建的Text添加到Widget Tree里面。由于新的Text与老的Text是有相同的类型,所以会使用老的Text的Element来显示自身。


image.png
然后重置State标记,这样,就做到了界面的刷新。

如果此时,MyWidget自身刷新了,情况会如何呢?

和上面一样,Flutter会创建出一个新的MyWidget出来。


image.png

然后用新的替换掉老的,由于新的与老的类型相同,所以依然会使用老的Element对自身进行显示。


image.png

5.总结

WidgetTree:用来描述界面Widget的配置,界面蓝图,我们可以理解为产品经理所做的原型设计。
ElementTree:用来决定Widget如何显示,可以理解为项目经理,协调和调整原型设计与开发。
其实还有一个RenderTree,相当于程序员的角色,对WidgetTree和ElementTree决定的界面进行实现。RenderTree我们平时开发基本接触不到,就不在这里讲了。

相关文章

网友评论

      本文标题:Flutter: WidgetTree、ElementTree

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