潍坊网站建设联系电话,大理市住房和城乡建设局网站,怎么用电脑做网站主机,网站备案手机号码一、Flutter框架的整体结构#xff1a;
Flutter是Google推出并开源的跨平台开发框架#xff0c;主打跨平台、高保真、高性能。开发者可以通过Dart语 言开发Flutter应用#xff0c;一套代码同时运行在ios和Android平台。不仅如此#xff0c;Flutter还支持Web、桌面、嵌 入应…一、Flutter框架的整体结构
Flutter是Google推出并开源的跨平台开发框架主打跨平台、高保真、高性能。开发者可以通过Dart语 言开发Flutter应用一套代码同时运行在ios和Android平台。不仅如此Flutter还支持Web、桌面、嵌 入应用的开发。Flutter提供了丰富的组件、接口开发者可以很快地为Flutter添加native扩展。同时 Flutter还使用skia引擎渲染视图这无疑能为用户提供良好的体验。 下面来看一下Flutter框架的整体结构组成 Flutter主要有三个主要组成部分框架层、引擎层、平台层。
框架层
Flutter框架建立在Dart语言的基础上
FoundationFramework的最底层叫Foundation其中定义的大都是非常基础的、提供给其他所 有层使用的工具类和方法
Animation动画相关的类库
Painting绘制库Painting封装了Flutter Engine提供的绘制接口主要是为了在绘制控制等固 定样式的图形时提供更直观、更方便的接口比如绘制缩放后的位图、绘制文本、插值生成阴影以 及在盒子周围绘制边框等等
Gesture提供了手势识别相关的功能包括触摸事件类定义和多种内置的手势识别器
Widgets在Flutter中一切UI皆widgetFlutter有两大不同风格的widget库 1一个是基于Material Design材料设计风格的组件库 2一个是基于cupertino的ios设计风格的组件库。
引擎层
Flutter引擎使用的是基于c的2D图形库称为Skia。在这一层中提供了Dart VM以提供一个执 行环境用于将Dart代码转换为本地平台可执行代码。Flutter引擎在Android、ios中运行以为widget 呈现对应的外观并根据特定平台通过Channel进行通信
平台层
Flutter根据不同平台提供了其特定的shell既Android Shell和IOS Shell这些shell用来托管Dart VM以提供对特定的平台API的访问
二、Flutter绘制原理
熟悉Flutter绘制原理有助于我们了解Flutter框架的原理机制。为了熟悉Flutter绘制原理我们先从屏幕 显示图像的基本原理开始说起
我们在买显示器时都会关注显示器的刷新频率那么对于手机屏幕也是一样的通常手机屏幕的刷新 频率是60Hz当然现在也有不少高刷新频率的手机也在推出如90Hz120Hz。 一般来说计算机系统中CPU、GPU和显示器以一种特定的方式协作CPU将计算好的显示内容提交 给GPUGPU渲染后放放帧缓冲区然后视频控制器按照VSync信号从帧缓冲区取帧数据传递给显示器 显示。当一帧图像绘制完毕后准备绘制下一帧时显示器就会发出一个垂直同步信号VSync所以 60Hz的屏幕就会一秒内发生60次这样的信号。
上面是CPU、GPU和显示器协作方式对于Flutter也不例外Flutter也遵循了这种模式 GPU的VSync信号同步给到UI线程UI线程使用Dart来构建抽象的视图结构这份数据结构在GPU线程 进行图层合成视图数据提供给 Skia引擎渲染为 GPU数据这些数据通过 OpenGL或者 Vulkan提供给 GPU。
三、Android UI绘制原理浅析
在上面Flutter绘制原理的阐述中提到最终交由Skia引擎来进行图形渲染听到这个词是不是可以联想到 我们的Android呢所以这里转一个视角对Android UI的绘制原理进行一个简单回顾
说到Android的UI绘制自然离不了CanvasAndroid上层的UI绘制几乎都通过Canvas来完成的那么 Canvas又是怎么完成UI绘制的呢接下来就让我们来通过追踪源码来一探究竟下面以Canvas绘制圆 形这个API来例进行分析
Canvas.javadrawCircle 其中它的父类是 BaseCanvas.javadrawCircle BaseCanvas.javanDrawCircle 此时就进入了c的世界了。
Canvas.cppdrawCircle SkCanvas.hdrawCircle 由此可以看出Android UI绘制最终还是交给Skia来完成的。
四、Flutter渲染流程 在Flutter框架中存在着一个渲染流程Rendering pipline。这个渲染流水线是由垂直同步信号 Vsync驱动的而Vsync信号是由系统提供的如果你的Flutter app是运行在Android上的话那 Vsync信号就是我们熟悉的Android那个Vsync信号。
当Vsync信号到来以后Fluttter框架会按照图里的顺序执行一系列动作
1.动画Animate
2.构建Build
3.布局Layout
4.绘制Paint
最终生成一个场景Scene之后送往底层由GPU绘制到屏幕上。
1、动画Animate阶段因为动画会随每个Vsync信号的到来而改变状态State所以动画阶段 是流水线的第一个阶段
2、构建Build在这个阶段Flutter在这个阶段那些需要被重新构建的Widget会在此时被重新构 建。也就是我们熟悉的StatelessWidget.build()或者State.build()被调用的时候
3、布局Layout阶段这时会确定各个显示元素的位置尺寸此时是 RenderObject.performLayout()被调用的时候
4、绘制Paint阶段此时是RenderObject.paint()被调用的时候
以上是整个渲染流程的一个大致的工作过程。
五、Flutter组件的生命周期 createState()当框架要创建一个StatefulWidget时它会立即调用State的createState()
initState()当State的构造方法被执行后会调用一次initState()需要指出的是initState()在State 生命周期内只被调用一次
build()这个方法会被经常调用比如setState以及配置改变都会触发build()方法的调用
didUpdateConfig()当收到一个新的config时调用
setState()当需要修改页面状态比如刷新数据等的时候我们可以通过调用setState来实现
dispose()当移除State对象时将调用dispose()通常在该方法中进行取消订阅取消所有动画 流等操作
六、Flutter渲染机制之三棵树
Flutter是一个优秀的UI框架借助它开箱即用的Widgets我们能够构建出漂亮和高性能的用户界面。那 这些Widgets到底是如何工作的又是如何完成渲染的。 所以接下来就来探析Widgets背后的故事-Flutter渲染机制之三棵树。
什么是三棵树 在Flutter中和Widgets一起协同工作的还有另外两个伙伴Elements和RenderObjects由于它们都是有着树形结构所以经常会称它们为三棵树。
1WidgetWidget是Flutter的核心部分是用户界面的不可变描述。做Flutter开发接触最多的就是 Widget可以说Widget撑起了Flutter的半边天
2ElementElement是实例化的 Widget 对象通过 Widget 的 createElement() 方法是在特定位 置使用 Widget配置数据生成
3RenderObject用于应用界面的布局和绘制保存了元素的大小布局等信息
初次运行时的三棵树:
初步认识了三棵树之后那Flutter是如何创建布局的以及三棵树之间他们是如何协同的呢接下来就 让我们通过一个简单的例子来剖析下它们内在的协同关系
class ThreeTree extends StatelessWidget {overrideWidget build(BuildContext context) {return Container(color: Colors.red,child: Container(color: Colors.blue));}
}
上面这个例子很简单它由三个Widget组成ThreeTree、Container、Text。那么当Flutter的 runApp()方法被调用时会发生什么呢下面在Flutter工程中先来构建这么一个简单的示例 运行一下 此时可以打开“Flutter Inspector” 那第二棵树在哪里呢此时需要跟一下源码了 总结一下就是
当runApp()被调用时第一时间会在后台发生以下事件
1Flutter会构建包含这三个Widget的Widgets树
2Flutter遍历Widget树然后根据其中的Widget调用createElement()来创建相应的Element对象 最后将这些对象组建成Element树
3接下来会创建第三个树这个树中包含了与Widget对应的Element通过createRenderObject()创建 的RenderObject
而整个状态过程可以用下图来描述 从图中可以看出Flutter创建了三个不同的树一个对应着Widget一个对应着Element一个对应着 RenderObject。每一个Element中都有着相对应的Widget和RenderObject的引用。可以说Element是存在于可变Widget树和不可变RenderObject树之间的桥梁。Element擅长比较两个Object在Flutter里面就是Widget和RenderObject。它的作用是配置好Widget在树中的位置并且保持对于相对应的 RenderObject和Widget的引用。
三棵树的作用:
那这三棵树有啥意义呢简而言之是为了性能为了复用Element从而减少频繁创建和销毁 RenderObject。因为实例化一个RenderObject的成本是很高的频繁的实例化和销毁RenderObject对 性能的影响比较大所以当Widget树改变的时候Flutter使用Element树来比较新的Widget树和原来的 Widget树接下来从源码中来体会一下 此时也是只更新对应的element接下来继续 总结如下
1如果某一个位置的Widget和新Widget不一致才需要重新创建Element;
2如果某一个位置的Widget和新Widget一致时两个widget相等或runtimeType与key相等则只需要修改RenderObject的配置不用进行耗费性能的RenderObject的实例化工作了
3因为Widget是非常轻量级的实例化耗费的性能很少所以它是描述APP的状态(也就是configuration)的最好工具
4重量级的RenderObject创建十分耗费性能则需要尽可能少的创建并尽可能的复用
因为在框架中Element是被抽离开来的所以你不需要经常和它们打交道。每个Widget的build BuildContext context方法中传递的context就是实现了BuildContext接口的Element。
更新时的三棵树
那如果此时我们修改一下程序 因为Widget是不可变的当某个Widget的配置改变的时候整个Widget树都需要被重建。例如当我们改变一个Container的颜色为橙色的时候框架就会触发一个重建整个Widget树的动作。因为有了Element的存在Flutter会比较 新的Widget树中的第一个Widget和之前的Widget。接下来比较Widget 树中第二个Widget和之前Widget以此类推直到Widget树比较完成。 Flutter遵循一个最基本的原则判断新的Widget和老的Widget是否是同一个类型 1如果不是同一个类型那就把Widget、Element、RenderObject分别从它们的树包括它们的子 树上移除然后创建新的对象 2如果是一个类型那就仅仅修改RenderObject中的配置然后继续向下遍历 在我们的例子中ThreeTree Widget是和原来一样的类型它的配置也是和原来的ThreeTreeRender一 样的所以什么都不会发生。下一个节点在Widget树中是Container Widget它的类型和原来是一样 的但是它的颜色变化了所以RenderObject的配置也会发生对应的变化然后它会重新渲染其他的 对象都保持不变。 上面这个过程是非常快的因为Widget的不变性和轻量级使得他能快速的创建这个过程中那些重量级 的RenderObject则是保持不变的直到与其相对应类型的Widget从Widget树中被移除。 注意这三个树配置发生改变之后Element和RenderObject实例没有发生变化。 当Widget的类型发生改变时: 和刚才流程一样Flutter会从新Widget树的顶端向下遍历与原有树中的Widget类型进行对比。 因为FlatButton的类型与Element树中相对应位置的Element的类型不同Flutter将会从各自的树上删除 这个Element和相对应的ContainerRender然后Flutter将会重建与FlatButton相对应的Element和 RenderObject。如下 很明显这个重新创建的过程相对耗时的但是当新的RenderObject树被重建后将会计算布局然后绘制 在屏幕上面。Flutter内部使用了很多优化方法和缓存策略来处理所以你不需要手动来处理这些。以上便是Flutter的整体渲染机制可以看出Flutter利用了三棵树很巧妙的解决的性能的问题。