一切皆Widget

Widget 渲染过程

Flutter把视图数据的组织和渲染抽象为三部分,即 Widget、Element 和 RenderObject。

Widget

Widget 是空间实现的基本逻辑单位,里面存储的是有关视图渲染的配置信息,包括布局、渲染属性、事件响应信息等。

页面渲染遵循“Simple is best”(简单是最好的)理念。Flutter 将 Widget 设计成不可变的,所以当视图渲染的配置信息发生变化时,Flutter 会选择重建 Widget 树的方式进行数据更新,以数据驱动 UI 构建的方式简单高效。

缺点是,因为涉及到大量对象的销毁和重建,所以会对垃圾回收造成压力。但是,Widget 本身并不涉及实际渲染位图,所以它只是一份轻量级的数据结构,重建成本很低。

另外,由于 Widget 的不可变行,可以以较低成本进行渲染节点复用,因此在一个真实的渲染树中可能存在不同的 Widget 对应同一个渲染节点的情况,这无疑又降低了重建 UI 的成本。

Element

Element 是 Widget 的一个实例化对象,它承载了视图构建的上下文数据,是连接结构化的配置信息到完成最终渲染的桥梁。

Flutter 渲染过程,可以分三步:

  • 首先,通过 Widget 树生成对应的 Element树;
  • 然后,创建相应的 RenderObject 并关联到 Element.renderObject 属性上;
  • 最后,构建成 RenderObject 树,以完成最终的渲染。

Element 同时持有 Widget 和 RenderObject,无论是 Widget 还是 Element,其实都不负责最后的渲染,只负责发号施令,真正干活儿的只有 RenderObject。

为什么不直由 Widget 命令 RenderObject 去干活儿,而是增加 Element 树?

Widget 直接命令,会极大地增加渲染带来的性能损耗。

因为 Widget 具有不可变性,但 Element 却是不可变的。实际上,Element 树这一层将 Widget 树的变化(类似 React 虚拟 DOM diff)做了抽象,可以只将真正需要修改的部分同步到真实的 RenderObject 树中,最大程度降低对真实渲染视图的修改,提高渲染效率,而不是销毁整个渲染视图树重建。

RenderObject

RenderObject 是主要负责实现视图渲染的对象。

渲染对象树在 Flutter 的展示过程分为四个阶段,即布局、绘制、合成和渲染。其中,布局和绘制在 RenderObject 中完成,Flutter 采用深度优先机制遍历渲染对象树,确定树中各个对象的位置和尺寸,并把它们绘制到不同的图层上。绘制完毕后,合成和渲染的工作则交给 Skia 搞定。

Flutter 通过引入 Widget、Element 与 RenderObject 这三个概念,把原本从视图数据到视图渲染的复杂构建过程拆分得更简单、直接,在易于集中治理的同时,保证了较高的渲染效率。

RenderObjectWidget 介绍

在 Flutter 中,布局和绘制工作实际上是在 Widget 的另一个子类 RenderObjectWidget 内完成的。RenderObjectWidget 源码如下:

RenderObjectWidget 是一个抽象类。这个类中同时拥有创建 Element、RenderObject,以及更新 RenderObject 的方法。但实际上,RenderObjectWidget 本身并不负责这些对象的创建与更新。

对于 Element 的创建,Flutter 会在遍历 Widget 树时,调用 createElement 去同步 Widget 自身配置,从而生成对应节点的 Element 对象。而对于 RenderObject 的创建与更新,其实是在 RenderObjectElement 类中完成。

在 Element 创建完毕后,Flutter 会调用 Element 的 Mount 方法。在这个方法里,会完成与之关联的 RenderObject 对象的创建,以及与渲染树的插入工作,插入到渲染树后的 Element 就可以显示到屏幕中了。

如果 Widget 的配置数据发生了改变,那么持有该 Widget 的 Element 节点会被标记为 dirty。在下一个周期的绘制时,Flutter 就会触发 Element 树的更新,并使用最新的 Widget 数据更新自身以及关联的 RenderObject 对象,接下来便会进入 Layout 和 Paint 的流程。而真正的绘制和布局过程,则完全交由 RenderObject 完成:

布局和绘制完成后,接下来的事情就交给 Skia 了。在 VSync 信号同步时直接从渲染树合成 Bitmap,然后提交给 GPU。

Widget 基础的更多相关文章

  1. iOS widget开发

    链接: iOS Widget开发 iOS开发之构建Widget iOS开发Widget iOS开发-widget基础 ios8新特性widget开发 ios 10 开发-widget实现 Widget ...

  2. 【转】谈谈Google Polymer以及Web UI框架的未来

    原文转自:http://www.csdn.net/article/2013-05-27/2815450-google-polymer 摘要:开发者Axel Rauschmayer在自己的博客上详解了G ...

  3. (24)odoo中模型标识汇总

    * 设置->技术->数据结构->模型                模型    模型描述    类型    瞬态模型account.account    科目    基础对象    ...

  4. Google Polymer以及Web UI框架

    时代在进步,原本前端只是用来简单的数据显示以及提交数据到后端处理逻辑的地方,而随着SPA的发展,前端的逻辑也越来越是庞大,恰巧,今天看微博的时候,发现一个概念讨论的比较多,就是 Web Compone ...

  5. 【JavaScript】谈谈Google Polymer以及Web UI框架的未来

    摘要:开发者Axel Rauschmayer在自己的博客上详解了Google Polymer的设计理念与组成架构,深得Polymer开发者的认同.他认为Polymer这样高互操作性的设计才应该是Web ...

  6. 十二、Android UI开发专题(转)

    http://dev.10086.cn/cmdn/bbs/viewthread.php?tid=18736&page=1#pid89255Android UI开发专题(一) 之界面设计 近期很 ...

  7. 【COCOS2DX-对28游戏开发】 Cocos2d-x-3c 道路设计 CocosBase CocosNet CocosWidget

    原文链接:http://blog.csdn.net/cocosviva/article/details/18970717 另一个比較不错的cocos2dx扩展库:https://github.com/ ...

  8. Android UI开发专题(转)

    http://dev.10086.cn/cmdn/bbs/viewthread.php?tid=18736&page=1#pid89255 Android UI开发专题(一) 之界面设计 近期 ...

  9. odoo 开发基础 -- 视图之widget

    Odoo 中的widget many2many_tags one2many_list selection progressbar selection statusbar handle monetary ...

随机推荐

  1. 关于selenium自动化对窗口句柄的处理

    首先什么是句柄?句柄就是你点击一个页面,跳转了一个新的窗口.你要操作的元素可能在原窗口上,也有可能在新窗口上. 看下图句柄1 句柄2 由这2张图可知,url不一样,证明他们是处于不同的界面,我要操作的 ...

  2. linux_密钥

    使用密钥文件.       这里假设主机A(192.168.100.3)用来获到主机B(192.168.100.4)的文件.   在主机A上执行如下命令来生成配对密钥: ssh-keygen -t r ...

  3. Android开发之输入框EditText介绍

    这篇文章主要为大家详细介绍了Android布局之输入框EditText设计,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 现在先简单介绍一下技术点: 1.如何使用圆角输入框和按钮背景 2.如何实现 ...

  4. 随笔编号-16 JAVA知识框架

    基于 J2EE 列举的知识架构,大体列举开发基础知识.帮助我随时查缺补漏,奉行好记性不如烂笔头.写了这该随笔,以便后续查询. 1  JAVA简介 2  JAVA编程环境 3  JAVA基本编程结构 4 ...

  5. C#开发BIMFACE系列5 服务端API之文件直传

    BIMFACE使用了分布式对象存储来存储用户上传的模型/图纸文件.如使用普通的文件上传接口, 文件流会通过BIMFACE的服务器,再流向最终的分布式存储系统,整个上传过程会受BIMFACE服务器的带宽 ...

  6. Django基础知识点

    HTTP协议:  请求方式: 有8种分别是GET POST DELTE PUT OPTIONS HEAD 状态码: 2xx   200 OK 3xx   重定向 4xx   请求的错误 5xx   服 ...

  7. 基于JRebel开发的MySQL Explain插件

    前言 我们在使用数据库时,为了使业务系统性能达到最优,往往都需要避免慢SQL查询,不能等到线上告警了再排查是否为慢SQL导致.在开发阶段,每个开发人员就应该针对自己写的SQL看是否可能为慢SQL,从而 ...

  8. Delphi - Indy TIdFTP控件实现文件的上传和下载

    FTP信息保存和获取 我们在做FTP相关开发时,为方便后续FTP切换,一般先把FTP账户信息保存到数据库表中,在使用时再通过Query获取出来. 一般通过如下方式获取到FTP相关信息,代码如下: // ...

  9. 探索Asp net core3中的 项目文件、Program.cs和通用host(译)

    引言 原文地址 在这篇博客中我将探索一些关于Asp.net core 3.0应用的基础功能--.csproj 项目文件和Program源文件.我将会描述他们从asp.net core 2.X在默认模版 ...

  10. java基础-多线程二

    java基础-多线程二 继承thread和实现Runnable的多线程每次都需要经历创建和销毁的过程,频繁的创建和销毁大大影响效率,线程池的诞生就可以很好的解决这一个问题,线程池可以充分的利用线程进行 ...