flutter原理,flutter编译原理

Flutter面试:渲染原理

页面中的各界面元素(Widget)以树的形式组织,即控件树。Flutter通过控件树中的每个控件创建不同类型的渲染对象,组成渲染对象树。而渲染对象树在Flutter的展示过程分为三个阶段:布局、绘制、合成和渲染。

成都创新互联服务项目包括化德网站建设、化德网站制作、化德网页制作以及化德网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,化德网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到化德省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!

(一)布局

Flutter采用深度优先机制遍历渲染对象树,决定渲染对象树中各渲染对象在屏幕上的位置和尺寸。在布局过程中,渲染对象树中的每个渲染对象都会接收父对象的布局约束参数,决定自己的大小,然后父对象按照控件逻辑决定各个子对象的位置,完成布局过程。

为了防止因子节点发生变化而导致整个控件树重新布局,Flutter加入了一个机制——布局边界(Relayout Boundary),可以在某些节点自动或手动地设置布局边界,当边界内的任何对象发生重新布局时,不会影响边界外的对象,反之亦然。

二)绘制

布局完成后,渲染对象树中的每个节点都有了明确的尺寸和位置。Flutter会把所有的渲染对象绘制到不同的图层上。与布局过程一样,绘制过程也是深度优先遍历,而且总是先绘制自身,再绘制子节点。

以下图为例:节点1在绘制完自身后,会再绘制节点2,然后绘制它的子节点3、4和5,最后绘制节点6。

可以看到,由于一些其他原因(比如,视图手动合并)导致2的子节点5与它的兄弟节点6处于了同一层,这样会导致当节点2需要重绘的时候,与其无关的节点6也会被重绘,带来性能损耗。

为了解决这一问题,Flutter提出了与布局边界对应的机制——重绘边界(Repaint Boundary)。在重绘边界内,Flutter会强制切换新的图层,这样就可以避免边界内外的互相影响,避免无关内容置于同一图层引起不必要的重绘。

重绘边界的一个典型场景是Scrollview。ScrollView滚动的时候需要刷新视图内容,从而触发内容重绘。而当滚动内容重绘时,一般情况下其他内容是不需要重绘的,这时候重绘边界就派上用场了。

(三)合成和渲染

终端设备的页面越来越复杂,因此Flutter的渲染树层级通常很多,直接交付给渲染引擎进行多图层渲染,可能会出现大量渲染内容的重复绘制,所以还需要先进行一次图层合成,即将所有的图层根据大小、层级、透明度等规则计算出最终的显示效果,将相同的图层归类合并,简化渲染树,提高渲染效率。

合并完成后,Flutter会将几何图层数据交由Skia引擎加工成二维图像数据,最终交由GPU进行渲染,完成界面的展示。

四、总结

咱们从各种业界主流跨端方案与Flutter的对比开始,到Flutter的简要介绍以及Flutter的运行机制,并以界面渲染过程为例,从布局、绘制、合成和渲染三个阶段讲述了Flutter的实现原理。相信大家对Flutter已经有一个整体认知,赶快一起上手操作起来吧!

Flutter Widget的渲染原理

抽象类Element 有mount方法

抽象类Widget 有createElement方法

RenderObjectWidget有createElement方法 和  createRenderObject方法

每一个Widget, 都有createElement方法,通过createElement方法 创建一个Element对象,

Element加入Element树中,它会创建三种Element ,每个Element 有个mount方法

第一种:RenderObjectElement(RenderObjectWidget的createElement方法)

mount方法中 调用

widget.createRenderObject(this) ,创建RenderObject对象,RenderObject对象加入Render树中

第二种:StatefulElement继承ComponentElement 

第三种:StatelessElement继承ComponentElement 

并不是所有的Widget都会被独立渲染!只有继承RenderObjectWidget的才会创建RenderObject对象! 

Flutter Provider实现原理

ChangeNotifierProvider、ChangeNotifier、Consumer的关系

1、ChangeNotifierProvider的父类ListenableProvider,ListenableProvider中实现了_startListening方法,_startListening主要是将Element的刷新方法添加到ChangeNotifier中的_listeners中

2、ListenableProvider将startListening传入其父类InheritedProvider,InheritedProvider主要是创建delegate = _CreateInheritedProvider。这个delegate就是_CreateInheritedProvider中delegate.startListening中的delegate

1、ChangNotifier负责更新UI

ChangeNotifier中notifyListeners,通过遍历_listeners,实现强制刷新UI

1、Consumer:包裹待刷新UI,在buildWithChild中将Provider.ofT(context)传入builder方法

2、解析 Provider.ofT(context)

Provider.ofT(context)是获取ChangeNotifier对象的方法

Provider.of中通过传入的context,获取父视图为inheritedElement的对象

获取到inheritedElement,通过inheritedElement.getValue的方式获取ChangeNotifier对象

7、继续查看inheritedElement?.value。通过断点可以进入_CreateInheritedProvider 类中get Value方法。调用startListening将当前Consumer包裹的element添加到Prorivder的_listeners数组中

通过调用notifyListeners()来刷新所有Consumer完整的Provider执行流程大概就是这样,流程图如下

flutter与原生交互方法和底层原理分析

1.环境准备, 参考链接

2.添加国内环境配置: 参考链接

3.新建

name: String类型,代表Channel的名字,也是其唯一标识符。

messager:BinaryMessenger类型,代表消息信使,是消息的发送与接收的工具。

codec: MessageCodec类型或MethodCodec类型,代表消息的编解码器。

fluuter中的MessageCodec用于二进制格式数据与基础数据之间的编解码。BasicMessageChannel所使用的编解码器就是MessageCodec。

iOS中,名称为FlutterMessageCodec,是一个协议,定义了两个方法:encode接收一个类型为id的消息,将其编码为NSData类型,而decode接收NSData类型消息,将其解码为id类型数据。

MessageCodec有多种不同的实现:

与MessageCodec不同的是,MethodCodec用于MethodCall对象的编解码,一个MethodCall对象代表一次从Flutter端发起的方法调用。MethodCall有2个成员变量:String类型的method代表需要调用的方法名称,通用类型(Android中为Object,iOS中为id)的arguments代表需要调用的方法入参

由于处理的是方法调用,故相比于MessageCodec,MethodCodec多了对调用结果的处理。当方法调用成功时,使用encodeSuccessEnvelope将result编码为二进制数据,而当方法调用失败时,则使用encodeErrorEnvelope将error的code、message、detail编码为二进制数据

MethodCodec有两种实现:

Flutter Bloc实现原理

1、继承SingleChildStatelessWidget,就是一个widget,通过create 传入一个Bloc对象

1、Bloc继承自BlocBase,BlocBase中创建了StreamController对象,为多订阅对象

其中onCounterEvent((event, emit)为初始化创建_eventController监听

2、Bloc中创建_eventController,为事件通知

3、BlocBase创建_stateController,为状态刷新通知

4、add方法是执行广播通知

5、处理完数据之后执行emit()方法,其中emit方法是stateController广播

1、 BlocBuilder继承自BlocBuilderBase,_BlocBuilderBaseState中build方法返回的是BlocListener

2、BlocListener继承BlocListenerBase,_BlocListenerBaseState中_subscribe()添加监听stateController广播通知

Flutter Channel底层原理分析

百度网盘flutter 见46-Flutter Channel

Flutter 提供三种Channel用作Flutter与iOS原生平台之间的数据传递

1.FlutterBasicMessageChannel: 用作频繁与原生交互

2.FlutterMethodChannel:用来调用方法,双向通讯

3.FlutterEventChannel:数据流通讯

三种Channel,都有以下成员变量

1.name: Channel 的唯一标识

在Flutter应用中,通常存在多个Platform Channel,使用name区分不同的Channel

2.messenger: 消息信使(BinaryMessenger)

负责Flutter与原生之间的相互通讯

[methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull  result) {

}];

setMethodCallHandler方法,MethodCallHandler放在FlutterBinaryMessageHandler中

创建一个FlutterMethodChannel,通过 setMethodCallHandler来进行消息处理,最终会为FlutterMethodChannel绑定一个FlutterBinaryMessageHandler,并以FlutterMethodChannel的name作为key,保存在一个Map结构中

先创建 FlutterEngine-FlutterViewController-FlutterMethodChannel,

调用setMethodCallHandler方法时,会进入FlutterEngine的setMessageHandlerOnChannel:binaryMessageHandle:中,在进入PlatformMessageRouter中进行储存


分享名称:flutter原理,flutter编译原理
URL地址:http://csdahua.cn/article/dsgdgdo.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流