likes
comments
collection
share

Flutter(三十五)-有状态和无状态Widget中的Element

作者站长头像
站长
· 阅读数 2

我们在上一篇文章中分析了一下Flutter的三棵树:Widget树Element树RenderObject树;这次我们来分析一下,有状态和无状态Widget中的Element有什么区别?

StatelessWidget的Element

我们首先看一下在StatelessWidgetelement的创建方法:

Flutter(三十五)-有状态和无状态Widget中的Element

StatelessWidget中通过createElement()方法创建了一个StatelessElement对象,而StatelessElement继承自ComponentElement,那么我们分析一下ComponentElement发现,在ComponentElement中有mount方法,我们在之前的文章中已经分析得知,Widget创建Element之后会在Element中调用mount方法,那么我们来分析一下此时的mount方法中做了什么事情:

Flutter(三十五)-有状态和无状态Widget中的Element

mount方法中,调用了_firstBuild()方法:

Flutter(三十五)-有状态和无状态Widget中的Element

_firstBuild()方法中去调用了rebuild()方法:

Flutter(三十五)-有状态和无状态Widget中的Element

之后,我们在rebuild()方法中会看到一个很重要的方法performRebuild()方法,继续往下走我们会发现只能看到performRebuild()方法的定义:

Flutter(三十五)-有状态和无状态Widget中的Element

因为此时我们已经进入了Element类内部,所以我们可以猜测到performRebuild()的实现应该在Element的子类中,最后我们在ComponentElement类中找到了performRebuild()方法的实现:

Flutter(三十五)-有状态和无状态Widget中的Element

performRebuild()方法中调用了build(),在ComponentElement类中build()方法也只有定义没有实现,那么我们只能再去ComponentElement的子类中寻找build方法的实现,很明显build的实现应该在StatelessElement中:

Flutter(三十五)-有状态和无状态Widget中的Element

StatelessElementbuild的实现为widget.build(this),我们通过Debug断点执行可以看到:

Flutter(三十五)-有状态和无状态Widget中的Element

  • widget:为MyApp
  • this:为当前StatelessElement对象;

也就是说,此时是MyApp在调用build方法并传递了一个参数StatelessElement,我们看一下MyApp的实现:

Flutter(三十五)-有状态和无状态Widget中的Element

这就是MyAppbuild被调用,然后渲染的流程;同时也可以得到BuildContext其实也就是Element(我们在之前的文章中使用StatefulElement也做过如下的操作):

Flutter(三十五)-有状态和无状态Widget中的Element

简单来说,StatelessWidget初始化时会通过createElement()方法创建一个StatelessElement,在createElement()方法中会调用mount方法,在mount方法中会调用Widgetbuild方法进行渲染并将Element自己传递出去;

StatefulWidget的Element

StatefulWidgetStatelessWidget稍有不同,在StatefulWidget中比StatelessWidget多了一个createState方法:

Flutter(三十五)-有状态和无状态Widget中的Element

我们先看一下createElement()方法创建StatefulElement的实现:

Flutter(三十五)-有状态和无状态Widget中的Element

StatefulElement的构造方法中,直接调用了widget.createState()来创建state对象,同时会将widget对象保存到state._widget中(这也是我们在State中能够通过widget来访问Widget中定义的属性的原因),把Element对象保存到state._element中(Widget本身与State对象共用同一个Element);

最终通过state对象来调用build方法:

Flutter(三十五)-有状态和无状态Widget中的Element

总结

  • Flutter中存在三棵树:Widget树Element树Render树Flutter引擎针对Render树中的对象渲染;并非每一个Widget都有Render树
  • 每一个Widget创建时,都会创建一个Element对象;
    • 通过createElement()方法创建Element对象,并将Element对象加入到Element树中,都会调用mount方法;
    • RenderElement主要是创建RenderObject
      • 通过mount方法创建RenderObject对象;
    • StatefulElement继承ComponentElement
      • 调用createState()方法,创建state对象;
      • Widget赋值给state对象的_widget属性;
      • 通过statebuild方法将自己也就是Element传出去;
    • StatelessElement继承ComponentElement
      • 主要调用build方法将Element传递出去;