微擎微网站开发,wordpress数据库怎么连接,5118营销大数据,兰州网络推广Flutter 既能保证很高的开发效率#xff0c;又能获得很好的性能。
这两年 Flutter 技术热度持续提高#xff0c;整个 Flutter 生态和社区也发生了翻天覆地的变化。目前Flutter 稳定版发布到了3.0#xff0c;现在已经支持移动端、Web端和PC端#xff0c;通过Flutter 开发的…
Flutter 既能保证很高的开发效率又能获得很好的性能。
这两年 Flutter 技术热度持续提高整个 Flutter 生态和社区也发生了翻天覆地的变化。目前Flutter 稳定版发布到了3.0现在已经支持移动端、Web端和PC端通过Flutter 开发的应用程序能够轻松的在各个平台迁移并获得很好的性能。另外Flutter 在 Github Star 数上排名已经进入了前20在跨端框架中已经成为稳稳的第一。
根据近几年实践统计Flutter 相比原生开发人效能提高近一倍且性能可以接近原生。
Flutter 源起 Flutter 属于在实现三个跨端框架方向之一的“自绘UI 原生”的范畴。在上一篇中也介绍过。
Flutter 实现一套自绘UI引擎并拥有一套自己的 UI 布局框架。
得益于但Dart开发语言的JIT 运行方式支持动态化的。因此在开发过程中 Flutter 的热重载可帮助开发者快速地进行测试、构建UI、添加功能并更快地修复错误。在 iOS 和 Android 模拟器或真机上可以实现毫秒级热重载并且不会丢失状态。
Flutter 从上到下分为UI框架层、引擎层和嵌入层。开发者基本上都是与UI框架层打交道。 UI 框架
UI 框架UI Framework指基于一个操作系统和浏览器之上快速开发GUI图形用户接口的框架。通常来讲平台只提供非常基础的图形 APICanvas如画线、画几何图形等。
可以想象一下如果没有UI 框架的封装而直接用 Canvas 来构建用户界面将会是怎样的一个体验和效率
简单来讲 UI 框架解决的主要问题就是如何基于基础的图形APICanvas来封装一套可以高效创建UI的框架。
各个平台 UI 框架的实现原理基本是相通的在介绍Flutter UI框架之前可以先了解平台图形处理的基本原理。操作系统AndroidIOS图像绘图的基本原理-CSDN博客 Flutter UI框架
Android SDK封装了Android操作系统API提供了一个“UI描述文件 XMLJava/Kotlin 操作 DOM”的UI 框架。iOS的 UIKit 对 View 的抽象也是一样的。他们都将操作系统API抽象成一个基础对象然后再定义一套规则来描述UI如UI树结构UI 操作的单线程原则等。
如果可以使用同一种编程语言开发在不同操作系统API上封装一个对上接口一致对下适配不同操作系统的中间层。那么我们就可以使用同一套代码编写跨平台的应用了。
而Flutter的原理正是如此它提供了一套Dart API然后在底层通过OpenGL这种跨平台的绘制库内部会调用操作系统API实现了一套代码跨多端。
由于Dart API也是调用操作系统API所以它的性能接近原生。
*注解
虽然Dart是先调用了OpenGLOpenGL才会调用操作系统API但是这仍然是原生渲染因为OpenGL只是操作系统API的一个封装库它并不像WebView渲染那样需要 JavaScript 运行环境和CSS渲染器所以不会有性能损失。Flutter 早期版本底层会调用 OpenGL 这样的跨平台库但在 iOS 设备上苹果提供了专门的图形库Metal使用 Metal可以在iOS上获得比OpenGL更好的绘图性能因此Flutter后来在 iOS 上会优先调用 Metal 只有当 Metal 不可用时才会降级到OpenGL。不过 Flutter 底层到底是调用的哪个库作为应用开发者是不需要关注的我们只需要知道调用的是原生的绘图接口可以保证高性能即可。 FlutterUI框架
简单概括组合响应式。
在Flutter开发UI中一切皆是Widget。我们要开发一个UI界面需要组合不同Widget来实现。而当UI要发生变化时我们不去直接修改DOM而是通过更新状态State让Flutter UI 框架来根据新的状态来重新构建UI。
先介绍一下BuildContext、RenderObject、Element它们是组成Flutter UI 框架的基石。 BuildContext
StatelessWidget和StatefulWidget的build方法都会传一个BuildContext对象。
Widget build(BuildContext context) {}
我们也知道在很多时候我们都需要使用这个context 做一些事比如
Theme.of(context) //获取主题
Navigator.push(context, route) //入栈新路由
context.findRenderObject() //查找当前或最近的一个祖先RenderObject
那么BuildContext到底是什么呢查看其定义发现其是一个抽象接口类
abstract class BuildContext {...
}
那这个context对象对应的实现类到底是谁呢以StatelessElement为例
class StatelessElement extends ComponentElement {...overrideWidget build() widget.build(this);...
}
发现build传递的参数是this。这个BuildContext的实现类就是StatelessElement。
虽然StatelessElement或StatefulElement并没有实现BuildContext接口但它们继承自Element类而Element类实现了BuildContext接口:
class Element extends DiagnosticableTree implements BuildContext {...
}
结论BuildContext就是widget对应的Element。所以我们可以通过context在StatelessWidget和StatefulWidget的build方法中访问到Element对象。 RenderObject
RenderObject的主要职责是Layout布局和绘制。
所有的RenderObject会组成一棵渲染树“Render Tree”。
RenderObject就是渲染树中的一个对象它可以实现事件响应以及布局、绘制、显示。
RenderObject类本身实现了一套基础的布局和绘制协议。 它本身没有定义坐标系统和具体的布局协议。为此Flutter框架提供了一个RenderBox 的盒模型布局和基于 Sliver 的按需加载模型。布局坐标系统采用笛卡尔坐标系屏幕的(top, left)是原点。
一个Element都对应一个RenderObject我们可以通过Element.renderObject 来获取。 Element
我们知道UI树其实是由一个个独立的Element节点构成。Element就是Widget在UI树具体位置的一个实例化对象。
所有Element的RenderObject构成一棵树我们称之为”Render Tree“即”渲染树“。
UI框架的三棵树Widget树、Element树、渲染树。 Element树根据Widget树生成而渲染树又依赖于Element树。
从创建到渲染的流程是根据Widget生成Element然后创建相应的RenderObject并关联到Element.renderObject属性上最后再通过RenderObject来完成布局排列和绘制。
其实对于开发者来说只需要关注Widget树就行Flutter框架已经将对Widget树的操作映射到了Element树上这可以极大的降低复杂度提高开发效率。
但是了解Element对理解整个Flutter UI框架是至关重要的Flutter正是通过Element这个纽带将Widget和RenderObject关联起来。
了解Element层不仅会帮助读者对Flutter UI框架有个清晰的认识而且也会提高自己的抽象能力和设计能力。
Element的生命周期
Framework 调用Widget.createElement 创建一个Element实例记为elementelement调用所对应Widget的createRenderObject方法创建与element相关联的RenderObject对象。然后element.attachRenderObject将renderObject添加到渲染树。此时element就处于“active”状态就可以显示在屏幕上了。当有父Widget的配置数据改变时同时其State.build返回的Widget结构与之前不同就需要重新构建对应的Element树。此时Element会先尝试复用旧树上相同位置的element。通过调用Widget.canUpdate方法判断newWidget与oldWidget的runtimeType和key是否同时相等如果同时相等就返回true复用旧Element。否则就创建新的Element。当Widget树结构发生了变化导致element对应的Widget被移除时该祖先Element就会调用deactivateChild 方法来移除element。Framework会调用element.deactivate 方法这时element状态变为“inactive”状态。“inactive”态的element将不会再显示到屏幕。如果element要重新插入到Element树其他的位置Framework会先将element从现有位置移除然后再调用其activate激活方法将其renderObject重新attach到渲染树。