重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
生命周期是别人封装好的一套方法接口,然后提供回调方法给我们调用,生命周期本质是回调方法;
我们提供的服务有:成都网站建设、成都网站设计、微信公众号开发、网站优化、网站认证、临沭ssl等。为1000多家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的临沭网站制作公司
1.监听widget的事件
2.初始化数据
创建数据
发送网络请求
3.内存管理
销毁数据,销毁监听者
销毁timer等
//1.StatelessWidget构造函数调用...1
//2.StatelessWidget的buil方法调用...2
//1.StatefulWidget的构造函数...1
//2.State的构造函数...2
//3.State的initState的方法...3
//4.State的build的方法...4
//5.State的dispose的方法...5
setState(() {})
可被
StatefulElement _element = context;
_element.markNeedsBuild();
替代
参考:
RenderObjectWidget 是 Widget 例如 SizeBox , Column 等
RenderObjectElement 是这类 Widget 生成的 Element 类型,
例如 SizeBox 对应 SingleChildRenderObjectElement (单子节点的 Element )
RenderObject 才是真正负责绘制的对象,其中包含了 paint , layout 等方法~
Text 组件为例:
class Text extends StatelessWidget
Text build返回的是
class RichText extends MultiChildRenderObjectWidget
MultiChildRenderObjectWidget - MultiChildRenderObjectElement
RenderObjectElement 会重写 mount
遍历 _parent (就是上个节点的 element ,这个 _parent 在每次的 mount 方法设置),一直遍历知道找到最近的一个 RenderObjectElement
在回顾下 inflateWidget
SingleChildRenderObjectElement
MultiChildRenderObjectElement
inflateWidget 会触发 RenderObjectWidget 的 createElement 创建 RenderObjectElement ,
再调用 RenderObjectElement 的 mount 方法
mount 方法调用 RenderObjectWidget 的 createRenderObject 方法创建 RenderObject
然后找到最近的一个父 RenderObjectElement 调用 insertRenderObjectChild 插入 RenderObject
(注意:这里不是 RenderObjectElement 的 child ,而是 RenderObjectElement 关联的 RenderObject 的 child , element 树里面都是 element , RenderObject 树里面都是 RenderObject )
MultiChildRenderObjectElement 多子节点挂载逻辑
多节点添加子节点逻辑
每个子节点的 parentData 的 after 用来指向前一个子节点 previous 指向下一个子节点
Flutter是谷歌公司推出的跨终端的开发框架,支持Android、iOS和WEB终端。1.0版在2018年12月5日发布,目前的最新版本是1.5,它采用的开发语言是Dart,Dart也是谷歌开发的计算机编程语言,语法类似C,是编译型语言:
hello world例子,打印字符串“Hello World!”:
1、没有桥接层
React Native、Weex等技术都是跨终端的框架,然而性能跟原生App存在很大差距。这是由于它们的工作原理决定的:
React Native、Weex等技术多了一个桥接层,所以界面渲染会慢一些,由于UI渲染非常频繁,想要不卡顿,基本上比较难,性能和用户体验跟原生代码有差距。而这恰恰是Flutter的优势所在:
Dart可以被编译成不同平台的本地代码,让Flutter不通过桥接层直接跟平台通信,自然性能会快一些。
2、编译执行
JavaScript是解释执行的,Dart是编译执行的,性能谁好一目了然。
3、Flutter Engine虚拟机
Flutter是依靠Flutter Engine虚拟机在iOS和Android上运行的,Flutter Engine使用C/C++编写,开发人员通过Flutter框架直接和API在内部进行交互,所以具有输入低延迟和UI渲染高帧速率的特点。除了这特点之外,Flutter还提供了自己的小部件,Flutter小部件是使用从React获取灵感的现代框架构建的。 中心思想是您使用小部件构建UI。
窗口小部件根据其当前配置和状态描述了它们的视图。 当窗口小部件的状态发生更改时,窗口小部件会重建其描述,框架将根据前面的描述进行区分,以确定底层呈现树从一个状态转换到下一个状态所需的最小更改。可以直接在OS平台提供的画布上进行描绘,也就是一些核心类库直接放到虚拟机里面,调用起来更快。
从它的系统结构可以看出,类似安卓的ART(Android Run Time)虚拟机,同样采用AOT(Ahead of TIme)技术,会在APP安装时就编译成机器语言,不再解释执行,从而优化了APP运行的性能。
4、自带渲染引擎
Flutter使用谷歌自己的Skia渲染引擎,而Android系统自带Skia引擎,iOS平台上Flutter也会把Skia引擎打包到APP中,从而实现了高效渲染。而React Native通过桥接层访问原生UI,操作频繁就容易出性能问题。
综合所述,Flutter 是性能最接近原生代码 的一种开发框架,未来也会是构建谷歌Fuchsia应用的主要方式,前途不可限量,唯一的问题就是需要学习一门新的语言:Dart,而有Java或者C#语言基础的程序员会比较容易学习。
开始FrameWork层会通知Engine表示自己可以进行渲染了,在下一个Vsync信号到来之时,Engine层会通过Windows.onDrawFrame回调Framework进行整个页面的构建与绘制。每次收到渲染页面的通知后,Engine调用Windows.onDrawFrame最终交给_handleDrawFrame()方法进行处理。最后会走到 WidgetsBinding.drawFrame() = buildOwner.buildScope(renderViewElement) = _dirtyElements[index].rebuild() = performRebuild() 这里会触发当前element的widget的build方法= updateChild() 注意这里已经是子节点进行接下来的操作了= 子节点update() = 子节点rebuild() = 子节点performRebuild() ...
小结:所以说在widget树中,越高层的 build() 里调用 setState() 会导致遍历所有的子节点=遍历所有子节点的子节点...
话术总结: setState() 会将当前的 element 标记为 脏 ,并交由 buildOwner ,由 buildOwner 加入自己的 脏列表中 ,等收到页面渲染的通知后(这里流程简略掉),会调用 buildOwenr. buildScope () ,这里会遍历 脏列表 然后每一个都会调用 rebuild() , rebuild() 又会调用 performRebuild() , performRebuild() 则会调用 build() 方法重建当前的 element ,然后调用 updateChild () 开始更新子节点,进而触发子节点的 rebuild() 方法,进行下一轮的周期...一直到最后一个节点
抽象类Element 有mount方法
抽象类Widget 有createElement方法
RenderObjectWidget有createElement方法 和 createRenderObject方法
每一个Widget, 都有createElement方法,通过createElement方法 创建一个Element对象,
Element加入Element树中,它会创建三种Element ,每个Element 有个mount方法
第一种:RenderObjectElement(RenderObjectWidget的createElement方法)
mount方法中 调用
widget.createRenderObject(this) ,创建RenderObject对象,RenderObject对象加入Render树中
第二种:StatefulElement继承ComponentElement
第三种:StatelessElement继承ComponentElement
并不是所有的Widget都会被独立渲染!只有继承RenderObjectWidget的才会创建RenderObject对象!
页面中的各界面元素(Widget)以树的形式组织,即控件树。Flutter通过控件树中的每个控件创建不同类型的渲染对象,组成渲染对象树。而渲染对象树在Flutter的展示过程分为三个阶段:布局、绘制、合成和渲染。
(一)布局
Flutter采用深度优先机制遍历渲染对象树,决定渲染对象树中各渲染对象在屏幕上的位置和尺寸。在布局过程中,渲染对象树中的每个渲染对象都会接收父对象的布局约束参数,决定自己的大小,然后父对象按照控件逻辑决定各个子对象的位置,完成布局过程。
为了防止因子节点发生变化而导致整个控件树重新布局,Flutter加入了一个机制——布局边界(Relayout Boundary),可以在某些节点自动或手动地设置布局边界,当边界内的任何对象发生重新布局时,不会影响边界外的对象,反之亦然。
二)绘制
布局完成后,渲染对象树中的每个节点都有了明确的尺寸和位置。Flutter会把所有的渲染对象绘制到不同的图层上。与布局过程一样,绘制过程也是深度优先遍历,而且总是先绘制自身,再绘制子节点。
以下图为例:节点1在绘制完自身后,会再绘制节点2,然后绘制它的子节点3、4和5,最后绘制节点6。
可以看到,由于一些其他原因(比如,视图手动合并)导致2的子节点5与它的兄弟节点6处于了同一层,这样会导致当节点2需要重绘的时候,与其无关的节点6也会被重绘,带来性能损耗。
为了解决这一问题,Flutter提出了与布局边界对应的机制——重绘边界(Repaint Boundary)。在重绘边界内,Flutter会强制切换新的图层,这样就可以避免边界内外的互相影响,避免无关内容置于同一图层引起不必要的重绘。
重绘边界的一个典型场景是Scrollview。ScrollView滚动的时候需要刷新视图内容,从而触发内容重绘。而当滚动内容重绘时,一般情况下其他内容是不需要重绘的,这时候重绘边界就派上用场了。
(三)合成和渲染
终端设备的页面越来越复杂,因此Flutter的渲染树层级通常很多,直接交付给渲染引擎进行多图层渲染,可能会出现大量渲染内容的重复绘制,所以还需要先进行一次图层合成,即将所有的图层根据大小、层级、透明度等规则计算出最终的显示效果,将相同的图层归类合并,简化渲染树,提高渲染效率。
合并完成后,Flutter会将几何图层数据交由Skia引擎加工成二维图像数据,最终交由GPU进行渲染,完成界面的展示。
四、总结
咱们从各种业界主流跨端方案与Flutter的对比开始,到Flutter的简要介绍以及Flutter的运行机制,并以界面渲染过程为例,从布局、绘制、合成和渲染三个阶段讲述了Flutter的实现原理。相信大家对Flutter已经有一个整体认知,赶快一起上手操作起来吧!