相关文章
Flutter 环境搭建以及填坑指南(Win10 系统且已有 Android 开发环境 )
Flutter 入门实现 ListView 列表页面以及收藏页面
Flutter Widget 静态布局实战
Flutter 容器类 Widget
简介
在 Flutter
中,一切皆 widget
。
那么什么是 widget
呢?
Widget 是 Flutter 功能的抽象描述,是视图的配置信息,同样也是数据的映射,是 Flutter 开发框架中最基本的概念。《引自极客时间-Flutter核心技术与实战》
从Android
开发的角度来看,widget
类似于 Android
中的 View
在Android
中 View
是最小的UI
单位,widget
则是 Flutter
中最小的 UI
单位。
图片引自:What is Flutter?
从上图可看出 Widget
主要有两种类型:StatelessWidget
和 StatefulWidget
。
那么这两个 widget
有什么区别呢?
二者的区别:有无状态管理。
StatelessWidget
中不需要管理Widget
内部的状态。而 StatefulWidget
中是需要管理Widget
内部的状态,通过是通过setState
来管理内部状态。
什么是状态管理呢?
我的理解是UI需要跟随用户的输入而进行改变。
Demo 示例解析
我们可以查看官方的计数器Demo,MyApp
只需要承载MyHomePage
,除此之外用户和UI没有直接的交互,因此这里使用StatelessWidget
是非常合适的。
再来看计数器Demo中点击按钮,计数器+1
的代码
MyHomePage
中需要根据用户和UI直接的交互,改变UI的值,因此这里使用StatefulWidget
是非常合适的。
为什么上面的描述我会用非常合适来形容呢?
因为StatefulWidget
也能实现StateflessWidget
的功能。
既然StateflessWidget
是可被替代的,那么他的作用是什么呢?
通过上面的分析,我们知道二者的区别也就是StatefulWidget
能通过setState()
来改变widget
的状态
那么我们从源码去找找,看看能找出StateflessWidget
存在的意义吗?
源码分析StateflessWidget
存在的意义
查看StatelessWidget,StatefulWidget
源码如下:
源码中重写的内容,确实和我们在创建StatelessWidget,StatefulWidget
是一样的。
那么接着往下查看,
找到了StatefulWidget
的State
抽象类中setState
方法,发现了markNeedsBuild
方法
这个方法的作用是:将element
标记为脏元素,并将其添加到全局的widget
中,调用了scheduleBuildFor
方法在下一帧中重建。。
上面的源码出现了新的内容element
,这又是什么东东呢?
仔细回看上面StatelessWidget,StatefulWidget
的源码,发现二者都会有一个方法,如下:
/// Creates a [StatefulElement] to manage this widget's location in the tree.
///
/// It is uncommon for subclasses to override this method.
/// StatefulWidget
@override
StatefulElement createElement() => StatefulElement(this);
/// StatelessWidget
@override
StatelessElement createElement() => StatelessElement(this);
通过注释也可以了解到,这里的Element
是用于管理在这个Widget
范围下的所有widget
,(Flutter 中万物皆widget,所以这个描述没毛病)。
点击深入源码发现StatefulElement 、StatelessElement
都继承了ComponentElement
。
通过上面的注释我们可以了解到
为了和RenderObjectElement
区分开,ComponentElement
并不是直接创建RenderObject
,而是通过其他 Element
间接创建的。
这里又出现新的内容:RenderObject
,这又是个什么东东?
RenderObject
在源码中的第一个注释是:An object in the render tree.
也就是渲染视图树上的一个对象。
在众多的注释中还说明了RenderObject
是负责layout and paint protocols
,也就是布局和绘制。
写到这里,我们不妨回想一下Widget
和Element
以及RenderObject
三者的关系。
Widget
是负责接收显示各个组件的绘制结果,而具体的绘制是通过创建RenderObject
去绘制,RenderObject
是通过RenderObjectElement
创建,而RenderObjectElement
又继承了Element
。
通过这么一顿分析,我们终于知道了Widget
的生成过程。
回到setState
的分析,我们发现StatefulElement
在调用setState
方法之后,该widget
下的所有widget
都会进行重建。
重建是需要耗时,所以StatefulElement 、StatelessElement
的使用场景就比较明确了。
总结:
- 使用
StatelessElement
可提高UI
的响应效率,优先使用StatelessElement
,在需要改变状态的情况下使用StatefulElement
。 Widget
是负责接收显示各个组件的绘制结果,而具体的绘制是通过创建RenderObject
去绘制,RenderObject
是通过RenderObjectElement
创建,而RenderObjectElement
又继承了Element
。