城市直播房产教育博客汽车
投稿投诉
汽车报价
买车新车
博客专栏
专题精品
教育留学
高考读书
房产家居
彩票视频
直播黑猫
投资微博
城市上海
政务旅游

Flutter3。0(framework框架)UI渲染

10月14日 小米粒投稿
  Flutter是谷歌开源的移动UI框架,可以快速在Android和iOS上构建出高质量的原生用户界面,目前全世界越来越多的开发者加入到Flutter的队伍。Flutter相比RN性能更好,由于Flutter自己实现了一套UI框架,丢弃了原生的UI框架,非常接近原生的体验。
  我们知道Flutter在UI绘制方面的效率是几乎接近原生的,这点比ReactNative要优秀很多,因为ReactNative是通过桥接转换然后去调用各自平台的UI系统(如iOS中的UIKit框架)提供的API来完成绘图。一、UI线程渲染
  为了揭秘Flutter高性能,本文从源码角度来看看Flutter的渲染绘制机制,跟渲染直接相关的两个线程是UI线程和GPU线程:
  UI线程:运行着UITaskRunner,是FlutterEngine用于执行Dartrootisolate代码,将其转换为layertree视图结构;
  GPU线程:该线程依然是在CPU上执行,运行着GPUTaskRunner,处理layertree,将其转换成为GPU命令并发送到GPU。
  通过VSYNC信号使UI线程和GPU线程有条不紊的周期性的渲染界面,本文介绍VSYNC的产生过程、UI线程在引擎和框架的绘制工作,下一篇文章会介绍GPU线程的绘制工作。1。1UI渲染原理
  私信发送核心笔记或手册;即可免费领取Flutter3。0学习进阶资料!1。1。1UI渲染概览
  通过VSYNC信号使UI线程和GPU线程有条不紊的周期性的渲染界面,如下图所示:
  当需要渲染则会调用到Engine的ScheduleFrame()来注册VSYNC信号回调,一旦触发回调doFrame()执行完成后,便会移除回调方法,也就是说一次注册一次回调;
  当需要再次绘制则需要重新调用到ScheduleFrame()方法,该方法的唯一重要参数regeneratelayertree决定在帧绘制过程是否需要重新生成layertree,还是直接复用上一次的
  UI线程的绘制过程,最核心的是执行WidgetsBinding的drawFrame()方法,然后会创建layertree视图树
  再交由GPUTaskRunner将layertree提供的信息转化为平台可执行的GPU指令。1。1。2UI绘制核心工作
  1)Vsync单注册模式:保证在一帧的时间窗口里UI线程只会生成一个layertree发送给GPU线程,原理如下:
  Animator中的信号量pendingframesemaphore用于控制不能连续频繁地调用Vsync请求,一次只能存在Vsync注册。
  pendingframesemaphore初始值为1,在Animator::RequestFrame()消费信号会减1,当而后再次调用则会失败直接返回;
  Animator的BeginFrame()或者DrawLastLayerTree()方法会执行信号加1操作。
  2)UI绘制最核心的方法是drawFrame(),包含以下几个过程:
  Animate:遍历transientCallbacks,执行动画回调方法;
  Build:对于dirty的元素会执行build构造,没有dirty元素则不会执行,对应于buildScope()
  Layout:计算渲染对象的大小和位置,对应于flushLayout(),这个过程可能会嵌套再调用build操作;
  Compositingbits:更新具有脏合成位的任何渲染对象,对应于flushCompositingBits();
  Paint:将绘制命令记录到Layer,对应于flushPaint();
  Compositing:将Compositingbits发送给GPU,对应于compositeFrame();
  Semantics:编译渲染对象的语义,并将语义发送给操作系统,对应于flushSemantics()。
  UI线程的耗时从doFrame(frameTimeNanos)中的frameTimeNanos为起点,以小节〔4。10。6〕Animator::Render()方法结束为终点,并将结果保存到LayerTree的成员变量constructiontime,这便是UI线程的耗时时长。1。1。3Timeline说明
  3)以上几个过程在Timeline中ui线程中都有体现,如下图所示:
  另外Timeline中还有两个比较常见的标签项
  FrameRequestPending:从Animator::RequestFrame到Animator::BeginFrame()结束;
  PipelineProduce:从Animator::BeginFrame()到Animator::Render()结束。二、渲染过程构建Widgets
  首先观察以下的代码片段,它代表了一个简单的widget结构:Container(color:Colors。blue,child:Row(children:〔Image。network(https:www。example。com1。png),Text(A),〕,),);
  当Flutter需要绘制这段代码片段时,框架会调用build()方法,返回一棵基于当前应用状态来绘制UI的widget子树。在这个过程中,build()方法可能会在必要时,根据状态引入新的widget。在上面的例子中,Container的color和child就是典型的例子。我们可以查看Container的源代码,你会看到当color属性不为空时,ColoredBox会被加入用于颜色布局。if(color!null)currentColoredBox(color:color!,child:current);
  与之对应的,Image和Text在构建过程中也会引入RawImage和RichText。如此一来,最终生成的widget结构比代码表示的层级更深,在该场景中如下图2:
  这就是为什么你在使用DartDevTools的Flutterinspector调试widget树结构时,会发现实际的结构比你原本代码中的结构层级更深。从Widget到Element
  在构建的阶段,Flutter会将代码中描述的widgets转换成对应的Element树,每一个Widget都有一个对应的Element。每一个Element代表了树状层级结构中特定位置的widget实例。目前有两种Element的基本类型:
  ComponentElement,其他Element的宿主。
  RenderObjectElement,参与布局或绘制阶段的Element。
  RenderObjectElement是底层RenderObject与对应的widget之间的桥梁。
  任何widget都可以通过其BuildContext引用到Element,它是该widget在树中的位置的上下文。类似Theme。of(context)方法调用中的context,它作为build()方法的参数被传递。
  由于widgets以及它上下节点的关系都是不可变的,因此,对widget树做的任何操作(例如将Text(‘A’)替换成Text(‘B’))都会返回一个新的widget对象集合。但这并不意味着底层呈现的内容必须要重新构建。Element树每一帧之间都是持久化的,因此起着至关重要的性能作用,Flutter依靠该优势,实现了一种好似widget树被完全抛弃,而缓存了底层表示的机制。Flutter可以根据发生变化的widget,来重建需要重新配置的Element树的部分。布局和渲染
  很少有应用只绘制单个widget。因此,有效地排布widget的结构及在渲染完成前决定每个Element的大小和位置,是所有UI框架的重点之一。
  在渲染树中,每个节点的基类都是RenderObject,该基类为布局和绘制定义了一个抽象模型。这是再平凡不过的事情:它并不总是一个固定的大小,甚至不遵循笛卡尔坐标规律(根据该极坐标系的示例所示)。每一个RenderObject都了解其父节点的信息,但对于其子节点,除了如何访问和获得他们的布局约束,并没有更多的信息。这样的设计让RenderObject拥有高效的抽象能力,能够处理各种各样的使用场景。
  在构建阶段,Flutter会为Element树中的每个RenderObjectElement创建或更新其对应的一个从RenderObject继承的对象。RenderObject实际上是原语:渲染文字的RenderParagraph、渲染图片的RenderImage以及在绘制子节点内容前应用变换的RenderTransform是更为上层的实现。更新UI
  上面介绍了Flutter在Framework级别渲染的流程(后续交给图像引擎),这只是一帧的流程。Flutter在更新UI上也有一些不同。更新WidgetTree
  之前提到了Widget的不可变性,所以每一帧都会调用build()方法返回widget树,即使是StatefulWidget,也只是根据不同的状态返回不同的widget树。但这样的话理论上会有大量的实例的产生和销毁,频繁GC,不过实际上,上面提到了Widget只是UI的配置,不负责实际的渲染,开销并没有那么大。更新ElementTree
  更重量级的ElementTree并不会全部重新渲染,而是根据WidgetTree的变化维护ElementTree(插入、删除、更新、移动),其中核心的几个方法包括:1。Element调用Widget。canUpdate(),去判断新的widget是否能用于更新Element。staticboolcanUpdate(WidgetoldWidget,WidgetnewWidget){returnoldWidget。runtimeTypenewWidget。runtimeTypeoldWidget。keynewWidget。}2。可以更新的话调用Element。update()Element。updateChild()继承类自行实现mustCallSupervoidupdate(covariantWidgetnewWidget){widgetnewW}framework。dartprotectedElementupdateChild(Elementchild,WidgetnewWidget,dynamicnewSlot){if(newWidgetnull){if(child!null)deactivateChild(child);}ElementnewCif(child!null){assert((){finalintoldElementClassElement。debugConcreteSubtype(child);finalintnewWidgetClassWidget。debugConcreteSubtype(newWidget);hasSameSuperclassoldElementClassnewWidgetC}());if(hasSameSuperclasschild。widgetnewWidget){if(child。slot!newSlot)updateSlotForChild(child,newSlot);newC}elseif(hasSameSuperclassWidget。canUpdate(child。widget,newWidget)){if(child。slot!newSlot)updateSlotForChild(child,newSlot);child。update(newWidget);assert(child。widgetnewWidget);assert((){child。owner。debugElementWasRebuilt(child);}());newC}else{deactivateChild(child);assert(child。parentnull);newChildinflateWidget(newWidget,newSlot);}}else{newChildinflateWidget(newWidget,newSlot);}assert((){if(child!null)debugRemoveGlobalKeyReservation(child);finalKeykeynewWidget?。if(keyisGlobalKey){key。debugReserveFor(this,newChild);}}());returnnewC}。。。staticboolcanUpdate(WidgetoldWidget,WidgetnewWidget){returnoldWidget。runtimeTypenewWidget。runtimeTypeoldWidget。keynewWidget。}
  newWidgetnull说明子节点对应的Widget已被移除,直接removechildelement(如有);childnull说明newWidget是新插入的,创建子节点(inflateWidget);child!null此时,分为3种情况:若child。widgetnewWidget,说明child。widget前后没有变化,若child。slot!newSlot表明子节点在兄弟结点间移动了位置,通过updateSlotForChild修改child。slot即可;通过Widget。canUpdate判断是否可以用newWidget修改childelement,若可以,则调用update方法;否则先将childelement移除,并通newWidget创建新的element子节点。更新RenderObjectTreeDartVM
  DartVM的内存回收机制采用多生代无锁垃圾回收器,专门为UI框架中常见的大量Widgets对象创建和销毁优化。基本的流程:DartVM的内存分配策略非常简单,创建对象时只需要在现有堆上移动指针,内存增长始终是线形的,省去了查找可用内存段的过程:
  Dart中类似线程的概念叫做Isolate,每个Isolate之间是无法共享内存的,所以这种分配策略可以让Dart实现无锁的快速分配。Dart的垃圾回收也采用了多生代算法,新生代在回收内存时采用了半空间算法,触发垃圾回收时Dart会将当前半空间中的活跃对象拷贝到备用空间,然后整体释放当前空间的所有内存:
  整个过程中Dart只需要操作少量的活跃对象,大量的没有引用的死亡对象则被忽略,这种算法也非常适合Flutter框架中大量Widget重建的场景。
  flutter基础到精通学习;dart语法基础到flutterUI、线程、启动流程、框架、性能监控等。
  私信获取全部学习资料!
  文末
  文章主要解析了flutter的UI线程渲染原理,以及渲染其过程。关于更多flutter的进阶学习。比喻(flutter动画原理、渲染机制、通信机制等。这只是部分)可以上面直达得到。
  私信:核心笔记或手册即可领取哦!
投诉 评论 转载

茅台冰激凌桥景房环游贵州后,我对福州多了几点思考8月中旬,去贵州浪了10天。走了贵阳、凯里、荔波、平塘、安顺、遵义、赤水等地方。贵州是自带流量的网红省份。不久之前,一位大V写过的贵州神盘花果园。这是个地处城市1。……华为智慧屏便携版正式预售配备10995毫安大电池前不久,华为举行了智慧屏新品发布会,带来了全新的华为Vision智慧屏86、Vision智慧屏75、华为智慧屏Z电竞版以及一款华为智慧屏便携版。10月20日晚8点,华为智慧屏便……库克终于出手,iPhone13最高直降1000元,果粉不用等一直以来手机界都有个金科玉律早买早享受、晚买有折扣,早买可以提前体验到新机更好的性能、拍照、网络质量等,而晚买则可以享更优惠的折扣。这不,作为苹果2021年下半年发布的常规旗舰……Reno7pro手机中的颜值担当非他莫属1外观设计很潮搭载一块6。55英寸、左上角的挖孔屏后面是全新的猫眼镜头模组、镜头模组带有呼吸灯、挺好看的。边框是直角设计、我最喜欢的直角边框了2配置方面……多件大事陆续发生,美元统治或将到头,人民币结算令也来了?在2022年的国际贸易结算中,好多国家慢慢开始出现了想摆脱美元的一个迹象,很多件大事在今年正陆续发生,世界刮起了反美元霸权的风,另一方面人民币的国际化也更进一步,那么美元的统治……Flutter3。0(framework框架)UI渲染Flutter是谷歌开源的移动UI框架,可以快速在Android和iOS上构建出高质量的原生用户界面,目前全世界越来越多的开发者加入到Flutter的队伍。Flutter相比R……BMW第二款纯电动摩托车CE04在国内发布将于年内上市早在2011年,BMW就通过Concepte概念车率先展示了电动摩托车的雏形,那个时候大家对电动化产品并不感冒,更别说是电动摩托车了。2015年,BMW在国内引入了BMWCev……2022年端边云协同的AI视觉产业研究报告AI视觉产业背景:AI视觉又称计算机视觉,得益于深度学习技术的快速发展,已于安防、金融、制造、零售等多领域实现规模化商用。2022年,AI视觉相关投融资热潮全面复苏,通用技术、……谢杏芳陪儿子训练!颜值气质看不出40岁,林丹收心后当家庭煮夫我们都知道林丹在羽毛球上有着很高的造诣,在世界赛场上多次夺冠、奥运赛场成功卫冕,也奠定了林丹在世界羽坛中的地位。2010年林丹牵手同为羽毛球运动员的谢杏芳领证结婚,但他却在婚内……中美伊俄日等国一季度粗钢产量都在下降,但印度增长5。9下面就是世界钢铁协会公布的2022年第一季度,全球前十大钢铁生产国数据表。我国一季度的粗钢产量约为2。434亿吨,继续位居全球各国之首。但与去年同期相比,我国粗钢产量缩减了10……20岁北京买房,明抢华妃一角,揭发潜规则,蒋欣有多不简单?原创西风娱2011年,一部后宫剧《甄嬛传》火遍全国,其中饰演里面华妃一角的蒋欣,也凭借此剧彻底爆红。但很多人都不知道,当时才28岁的蒋欣已经是圈内的老戏骨,她在演华……早上好,最新版漂亮的早晨问候动态图片,最温馨的早安问候祝福清晨的霞光无比灿烂,扫除你一切的忧烦,早上好!如果有一天,让你心动的再也感动不了你,让你愤怒得再也激怒不了你,让你悲伤的再也不能让你流泪,你便知道这时光、这生活给了你什么……
考研如何提高复习效率第一季度造句用第一季度造句大全格力小太阳取暖器到底好不好绶带造句用绶带造句大全溪木源公开独家痘敏肌疗愈机密!愈创木精华给你全周期祛痘护理体双节带宝宝出游穿什么合适三件套最灵活自觉自愿造句用自觉自愿造句大全人际交往如何改善不合群心理冬天的太阳茶虽好喝,但也要注意饮用梨不能和什么一起吃犀照牛渚的故事湖人130114老鹰!无解的不是4连胜,而是詹姆斯赛后这番话记忆的深处的作文瓦莱斯《起义者》主要内容简介及赏析世界因环保而美好地图软件哪个好(专业地图软件有哪些)WTTC2020年全球旅游业亏损近4。5万亿美元Windows12真的即将到来吗?不仅仅是谣言有关珍惜亲情的优秀作文高三英语教学个人总结sony投影仪使用方法产品新人第一次独立负责新功能的上线如何才能住肠梗阻的症状及治疗这些症状可能是肠梗阻要小心

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找江西南阳嘉兴昆明铜陵滨州广东西昌常德梅州兰州阳江运城金华广西萍乡大理重庆诸暨泉州安庆南充武汉辽宁