首页 > 其他分享 >Flutter框架渲染流程与使用

Flutter框架渲染流程与使用

时间:2024-01-22 10:34:42浏览次数:33  
标签:Widget 调用 渲染 Buffer 流程 GPU Flutter

转自:https://www.cnblogs.com/zhou--fei/p/17068412.html   Flutter简述 Flutter是一个UI框架, 可以进行移动端(iOS, Android),Web端, 桌面端开发,它是一个跨平台解决方案。 Flutter的特点:美观,快速,高效,开放。 美观:Flutter内置了美丽的Material Design和 Cupertino widget, 方便开发出美丽的页面。 快速:Flutter的UI渲染性能好,在生产环境下,Flutter将代码编译成机器码执行,并充分利用GPU的图形加速能力,可以实现60FPS。Debug环境下则使用JIM,提升了开发效率。 Flutter引擎使用C++编写,包含了高效的Skia 2D渲染引擎,Dart运行时和文本渲染库。 高效:Hot reload, 在前端不是新鲜的东西,在移动端却并不常见。 开放:Flutter是开放的,它是一个完全开源的项目。 Flutter有一统大前端的野心,并且它正在侵蚀iOS,Andriod这些原生开发。   跨平台解决方案历史 第一个阶段:通过webView iOS端有UIWebView, Android端WebView 最早出现的跨平台框架是基于JavaScript和WebView的,代表框架有PhoneGap, Apache Cordova, Ionic等。 主要是通过Html, Css开发页面。对于调用的一些本地服务如相机,蓝牙等。需要通过JS进行桥接调用Native功能的一些功能代码,本身的性能和体验并不理想。 0   第二阶段:React Native RN是FaceBook早先开源的JS框架React在原生移动平台的衍生产物,目前支持iOS和安卓两大平台。 RN是使用JS语言,使用类似于HTML的JSX, 以及CSS来做移动开发。 使用原生自带的UI组件实现核心的渲染引擎,从而保证了良好的渲染性能。 但是RN的本质是通过JavaScript VM调用原生接口,通信相对比较低效,并且框架本身不负责渲染,而是间接通过原生进行渲染的。   0 第三个阶段:Flutter 拥有自渲染闭环,是理想的跨平台框架。 0 安卓原生渲染流程: 1.通过Java语言,调用Android框架提供的framework的API 写出页面布局。 2.页面布局通过Android框架中framework进行翻译,将翻译的结果提交给Skia。 3.Skia给CPU/GPU 提供数据进行渲染。 Flutter渲染流程: 1.通过Dart语言,调用Flutter框架提供的framework的API 写出页面布局。 2.页面布局通过Flutter框架中framework进行翻译,将翻译的结果提交给Skia。 3.Skia给CPU/GPU 提供数据进行渲染。 从上面可以发现,Flutter和安卓的渲染流程是一样的。 0 RN的渲染流程 1.通过JS, JSX, CSS, Redux等调用React框架提供的API编写页面布局。 2.React框架通过JavaScript VM, Bridge将JS布局转换成原生布局。 3.原生页面布局通过Android框架中framework进行翻译,将翻译的结果提交给Skia。 4.Skia给CPU/GPU 提供数据进行渲染。 RN渲染增加了1,2步骤的转换,造成了性能消耗。所以RN的性能没有Flutter的高。 Flutter不需要依赖原生控件,利用Skia绘图引擎,直接通过CPU,GPU进行绘制。和安卓的原生绘制流程一样。 而像RN框架,必须先通过桥接的方式转成原生调用,然后再进行渲染。存在性能消耗。   0 Flutter绘制原理 1.GPU将VSync绘制信号同步到UI线程。 2.UI线程用Dart将Flutter代码构建图层树Layer Tree。 3.图层树Layer Tree在GPU线程内的Compositor进行合成。 4.Compositor合成的结果交给Skia进行渲染。 5.Skia渲染的结果通过OpenGL或Vulkan交给GPU进行图像绘制。 6.GPU绘制完成后把图像放入到双缓存的Back Buffer,等下一个VSync来时,系统从Back Buffer复制到Frame Buffer并产生新一轮的CPU/GPU绘制过程。 上面是Flutter完整的渲染闭环,这是它和ReactNative的本质区别。 ReactNative是没有自己的渲染闭环的,它是通过JS VM调用系统组件,使用的iOS、安卓的原生渲染。   图像的显示原理 在屏幕上看到的任何东西都是图像,包括图片,GIF图像,视频。 当图片连续播放的频率超过16帧时,人眼就会感到非常流畅。当小于16帧时就会感到卡顿。 帧率(fps): Frames Per Second, 每秒生成多少帧图像。 刷新率:显示屏的频率,比如iPhone的屏幕每秒刷新60下,表示为60Hz。   帧率和刷新率的关系 GPU/CPU生成图像(每秒生成多少张图片是帧率)放入Buffer中,屏幕从Buffer中取图像,刷新(每秒刷新多少次是刷新率)后显示。这是一个生产者-消费者模型。 很容易产生的问题是:GPU在新的一帧图片写入一半时,屏幕从中取出图像展示。此时会取出一张上半部分和下半部分不一致的图像。 显示出来的图像出现上半部分和下半部分明显偏差的现象,我们称为“tearing”(撕裂)。   0   双重缓存和VSync 为了解决“tearing”(撕裂)问题,就出现了双重缓存和VSync。 0 两个缓存分别为Back Buffer和Frame Buffer, GPU向Back Buffer写数据,屏幕从Frame Buffer读数据。VSync信号负责从Back Buffer到Frame Buffer的复制操作。底层的复制是用“指针交换”的假复制,效率高。 工作流程: 某个时间点,一个屏幕刷新周期完成,VSync信号产生,先完成复制操作,然后通知CPU/GPU绘制一帧图像。 复制操作完成后,开始下一个刷新周期,将刚复制到Frame Buffer的数据显示到屏幕上。 在这种模型下,只有当VSync信号产生时,CPU/GPU才开始绘制。   双重缓存存在的问题 双重缓存的缺陷:当CPU/GPU绘制一帧的时间过长(比如超过16ms一个刷新周期时),会产生Jank(画面停顿,甚至空白),VSync信号是在一个刷新周期结束后产生的。 0 三重缓存 在每次VSync信号来时,多缓存一个Buffer作为备用。   渲染引擎skia skia是Flutter向GPU提供数据的途径。 skia是一个C++编写的开源形库。 目前skia是安卓的官方图像引擎,所以Flutter的安卓应用SDK无需内嵌Skia引擎。 而对于iOS来说,Skia引擎需要嵌入到iOS SDK中,替代了iOS必源的Core Graphics / Core Animation / Core Text, 所以Flutter iOS SDK打包的APP包体积比安卓的大。 因为底层渲染能力的统一,上层开发接口和功能也就是统一的。skia保证了同一套代码调用在iOS和Android上渲染效果是完全一致的。 0   创建一个Flutter项目 命令行创建flutter项目 项目名称不支持中文,不支持大小,可以使用_进行链接

1 flutter create flutter_demo

VSCode环境安装插件

1 2 3 Flutter, Dart, Code Runner

Flutter项目启动方式有三种:冷启动,热启动(hotReload),热重载(hotRestart)。

冷启动:代码和Flutter框架都没有加载和运行,需要从磁盘加载到内存进行运行,过程比较久,通常需要1min-5min。 热启动 hotReload:重新运行widget中的build方法。 热重载 hotRestart:重新运行APP的main入口函数,重新运行一遍程序。 Material是什么 Material是google推出的套设计风格,或者叫设计规范。里面包含了很多设计规范,如:颜色,文字排版,响应动画与过度等。 在Flutter中高度集成Material风格的Widget。 Widget是什么 Flutter中万物皆Widget。在iOS或安卓中,我们的页面有很多种类:应用Application, 视图控制器ViewController, 视图View, Button按钮等。 但是在Flutter中,这些东西都是不同的Widget。 而在我们的APP中,所有能看到的内容几乎都是Widget, 甚至内边距设置都是使用Padding的Widget来做的。 Flutter项目的入口 Flutter项目的入口是lib/main.dart下的main函数。 在main函数内部,需要运行函数runApp(widget app);, runApp函数是Flutter提供的一个全局APP运行函数入口。
1 runApp(widget app);

最简单的Flutter项目Demo

1 2 3 4 import 'package:flutter/material.dart'; void main(List<String> args) {   runApp(Text('Hello Flutter')); }

此时报错:没有找到排版方向

原因是Flutter是面向全世界很多国家的,有的国家排版是从左往右,有的是从右往左。所以需要用户自己设置。 0 这里需要明确指定排版方向:TextDirection.ltr。 在Flutter中万物都是widget,所以如果要设置center, padding ,margin等都是写对应的widget。 修改报错后,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 void main(List<String> args) {   runApp(     Center(         child:Text('Hello Flutter',         textDirection: TextDirection.ltr,         style: TextStyle(           color: Colors.red,           fontSize: 30,         ),       )     )   ); }
MaterialApp:采用了Google的Material设计设计规范的Widget,里面默认设置了文字排版方向等设置。 Scaffold:脚手架Widget, 用于快速搭建页面机构,提供了不同位置的命名可选参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import 'package:flutter/material.dart'; /*   MaterialApp:采用了Google的Material设计设计规范的Widget,里面默认设置了文字排版方向等设置。   Scaffold:脚手架Widget, 用于快速搭建页面机构,提供了不同位置的命名可选参数。   debugShowCheckedModeBanner: 去掉右上角的debug条 */ void main(List<String> args) {   runApp(     MaterialApp(       debugShowCheckedModeBanner: false,       home:Scaffold(           appBar: AppBar(title: Text('第一个Flutter程序'),),           body: Center(             child:Text('Hello Flutter',             style: TextStyle(               color: Colors.blue,               fontSize: 30,             ),           )         ),       )     )   ); }
StatelessWidget StatelessWidget:在运行过程中,组件内容是固定的,没有状态修改的。 Widget中没有数据改动,只使用固定的数据展示或者只使用从父Widget继承过来的Widget时,使用StatelessWidget。 继承StatelessWidget产生的子Widget需要重新build方法,并在build方法里返回要展示的widget。 build方法是无法主动调用的。只能在数据改动时系统来调用。 build方法调用时机: 1.当StatelessWidget第一次插入到Widget树时(第一次被创建时) 2.当父Widget发生改变时,子Widget需要被重新构建 3.当依赖的InheritedWidget的数据发送改变时,被重新调用。 StatefulWidget 在运行过程中,状态(data)会产生改变,导致页面展示内容发生改变。 如果想使用StatefulWidget创建有状态变化的Widget, 需要一个State对象一起来实现。 StatefulWidget内部无法写var属性, 因为它继承自Widget,Widget是被@immutable修饰,不可改变。所以它的状态改变要在别的类(State)中实现。 State:在创建的State子类中添加var属性,并将其与Widget状态绑定,当有新的状态改变时,需要调用setState((){})进行更新状态 Flutter的状态更新和React的机制一样,需要调用setState通知框架进行页面更新。 与Vue不同的是Vue实例使用的是双向绑定,内部对属性做了监听,无需手动调用setState进行通知更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 /*   StatefulWidget内部无法写var属性, 因为它继承自Widget,Widget是被@immutable修饰,不可改变。所以它的状态改变要在别的类(State)中实现。   State:在创建的State子类中添加var属性,并将其与Widget状态绑定,当有新的状态改变时,需要调用setState((){})进行更新状态   Flutter的状态更新和React的机制一样,需要调用setState通知框架进行页面更新。   与Vue不同的是Vue实例使用的是双向绑定,内部对属性做了监听,无需手动调用setState进行通知更新。 */ class PageContent extends StatefulWidget {   @override   State<StatefulWidget> createState() {     return PageContentState();   } } class PageContentState extends State<PageContent> {   var flag = true;   @override   Widget build(BuildContext context) {     return Center(         child:Row(           mainAxisAlignment: MainAxisAlignment.center,           children:[             Checkbox(               value: flag,               onChanged: (value) {                 setState(() {                   flag = value;                 });               },),             Text('Hello World')           ]         )     );   }     }
声明式编程和命令式编程 iOS,安卓使用的是命令式编程,平时涉及到的是属性,成员变量。 vue, react, flutter是声明式编程,平时涉及到的是State状态,平时开发是只需要管好状态,显示内容有框架自动帮忙更新上去。 Flutter修饰符 @immutable修饰符表示Widget类是不可改变的,里面的属性都是final类型的。 required可选变量 必传修饰符, 用于表示命名可选变量为必传参数。
1 2 3 4 5 6 7 8 @immutable abstract class Widget extends DiagnosticableTree     const Checkbox({     Key? key,     required this.value,     this.tristate = false,     required this.onChanged,

 

 

标签:Widget,调用,渲染,Buffer,流程,GPU,Flutter
From: https://www.cnblogs.com/jacksplwxy/p/17979442

相关文章

  • Micro 接口运行流程
    1.程序运行2初始化接口清单(TSysInterMst)3.静态函数(GlobalManager)-----------------------------------1.控制器(Run)2.账号/密码/接口名/参数(Body),使用zip压缩传参3.验证账号/密码4.验证接口名/参数5.执行接口(接口名、参数)6.默认函数(ImportJson)6.1.取字段映射(TSysInterMst、TSysInter......
  • Go语言核心36讲 24 | 测试的基本规则和流程(下)
    你好,我是郝林。今天我分享的主题是测试的基本规则和流程的(下)篇。Go语言是一门很重视程序测试的编程语言,所以在上一篇中,我与你再三强调了程序测试的重要性,同时,也介绍了关于gotest命令的基本规则和主要流程的内容。今天我们继续分享测试的基本规则和流程。本篇代码和指令较多,你......
  • Go语言核心36讲 23 | 测试的基本规则和流程 (上)
    你好,我是郝林,今天我分享的主题是:测试的基本规则和流程(上)。你很棒,已经学完了本专栏最大的一个模块!这涉及了Go语言的所有内建数据类型,以及非常有特色的那些流程和语句。你已经完全可以去独立编写各种各样的Go程序了。如果忘了什么,回到之前的文章再复习一下就好了。在接下来的日......
  • HarmonyOS4.0 系列——06、渲染之条件渲染、循环渲染以及懒加载渲染
    HarmonyOS4.0系列——06、渲染之条件渲染、循环渲染以及懒加载渲染if/else:条件渲染ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态,使用if、else和elseif渲染对应状态下的UI内容。写法和TS的一样,简单看一下即可@Entry@ComponentstructIfForEach{@State......
  • 在Markdown中使用mermaid画图之流程图
    流程图流程图由流程图方向、节点、节点形状、节点间关系构成声明流程图flowchartLR//flowchart声明为流程图、LR确定流程图从左至右的方向 id1[test1]//id--创建出一个节点、括号内为该节点显示的内容 id2[test2] id3[test3]流程图的方向有以下几种选择:TB-从上到......
  • 基于物理的渲染(3):OSG中PBR实践
    1.1单光源直接光照voidmain(){ //创建小球几何 osg::ref_ptr<osg::ShapeDrawable>sphere=newosg::ShapeDrawable; sphere->setShape(newosg::Sphere(osg::Vec3(0,0,0),radius)); sphere->setColor(osg::Vec4(col)); //创建小球节点 osg::ref_ptr<osg::Geode>pbr......
  • shiro缓存配置流程
    以前搞shiro的时候没有刻意去研究过这些配置文件,导致用shiro的时候也是迷迷糊糊,惭愧啊,要想成为人上人,读源码,懂配置是真滴重要!安全管理器配置(SecurityManager)配置项意思一setCacheManager配置缓存管理器用来缓存realm和session信息二setRealm登录时假如用的UsernamePasswordToken,......
  • 正确理解springboot国际化简易运行流程
    看源码可以看出–》大致原理localeResolver国际化视图(默认的就是根据请求头带来的区域信息获取Locale进行国际化)返回的本地解析是根据响应头来决定的)接着按住ctrl点localeresolver可知localeresolver是一个接口于是有了这些我们只需通过继承LocaleResolver来自定义我们自己的Loca......
  • 从零开始:直播电商APP开发全流程解析
    本篇文章,小编将从零开始,全面解析直播电商APP的开发流程,涵盖了关键的技术要点和开发阶段的关键步骤。 第一阶段:需求分析与规划此阶段的关键任务包括:1.用户需求调研2.功能规划3.技术选型第二阶段:设计与原型设计阶段是将需求转化为可执行计划的关键环节。在这一阶段,团队需要完成以下......
  • VMware Aria Automation Orchestrator 8.16 - 现代工作流程自动化平台
    VMwareAriaAutomationOrchestrator8.16-现代工作流程自动化平台请访问原文链接:https://sysin.org/blog/vmware-aria-automation-orchestrator/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org现代工作流程自动化平台VMwareAriaAutomationOrchestratorVMwar......