Flutter渲染流程分析

启动流程

void runApp(Widget app) {
  WidgetsFlutterBinding.ensureInitialized()
    ..scheduleAttachRootWidget(app)
    ..scheduleWarmUpFrame();
}

整体流程

1、创建根Element

RenderObjectToWidgetElement为整个页面的根Element。
继承关系:RenderObjectToWidgetElement—>RootRenderObjectElement—>RenderObjectElement—>Element

  • RenderObjectToWidgetAdapter–>RenderWidget–>Widget
  • RenderObjectToWidgetElement

使用RenderObjectToWidgetAdapter创建RenderObjectToWidgetElement对象。
在创建RenderObjectToWidgetAdapter时,传入的RenderView和根Widget,根Widget作为RenderObjectToWidgetAdapter的child。
RenderObjectToWidgetAdapter是RenderObjectWidget子类。

2、执行根Element挂载

挂载时,根Widget是StatelessWidget或StatefullWidget,会进行子元素挂载,创建Widget树、Element树和RenderObject树
如何创建RenderObject树的?

3、请求VSYN信号

在应用启动过程有两处请求VSYNC信号的调用,分别在attachRootWidget时,及之后。

  • scheduleWarmUpFrame()
  • SchedulerBinding.instance.ensureVisualUpdate()

State

  • initState()
  • didUpdateWidget()
  • reassemble
  • setState
  • deactivate()
  • activate()
  • dispose()
  • build()
  • didChangeDependencies()

Element

  • mount()
  • unmount()
  • update()
  • updateChild()
  • updateSoltForChild()
  • attachRenderObject()
  • inflateWidget()
  • activate()
  • deactivate()
  • markNeedsBuild()
  • performRebuild()
  • rebuild()

在这里插入图片描述

相关文件

  • lib/src/widgets/binding.dart
  • lib/src/widgets/framework.dart
//lib/src/widgets/binding.dart
void runApp(Widget app){
	WidgetsFlutterBinding.ensureInitialized()
        //创建根Element并执行挂载操作
		..scheduleAttachRootWidget(app)
        //触发请求VSYNC信息
		..scheduleWarmUpFrame();
}

//WidgetsBinding  
void scheduleAttachRootWidget(Widget rootWidget){
	attachRootWidget(rootWidget);
}

//RenderObjectToWidgetApater extends RenderObjectWidget
void attachRootWidget(Widget rootWidget){
	//构建RenderObjectToWidgetObject对象时,将rootWidget赋值给了它的child字段
	_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
		container: renderView,
		child: rootWidget,
	).attachToRenderTree(buildOwner, renderViewElement as RenderObjectToWidgetElement<RenderBox>);
    //触发请求VSYNC信息
    SchedulerBinding.ensureVisualUpdate();
}

//RenderObjectToWidgetAdapter 
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element]){
	//在上述调用中,element=null
	if(element == null){
		owner.lockState((){
			element = createElement();
			element.assignOwner(owner);
		});
		owner.buildScope(element, (){
			//此时element已经有child, 在createElement已经将widget传递过去
			element.mount(null,null);
		});
	}else{
	}
}

//RenderObjectToWidgetAdapter
RenderObjectToWidgetElement<T> createElement(){
	return RenderObjectToWidgetElement<T>(this);
}

//RenderObjectToWidgetElement extends RootRenderObjectElement extends RenderObjectElement

//RenderObjectToWidgetElement
void mount(Element parent, Object? newSolt){
	super.mount(parent, newSolt);
	_rebuild();
}

void _rebuild(){
	//触发widget创建widget
	_child = updateChild(_child, wiget.child, _rootChildSolt);

}

RenderObjectElement在mount时,会通过widget创建RenderObject对象。

//lib/src/widgets/framework.dart
//RenderObjectElement
void mount(){
	_renderObject = (widget as RenderObjectWidget).createRenderObject(this);
	attachRenderObject(newSolt);
	super.performRebuild();//基类标记为_dirty
}

挂载流程

RenderObjectElement在mount时会创建RenderObject对象。

Element.mount(Element parent,)
ComponentElement._firstBuild();
Element.rebuild();
ComponentElement.performBuild();
build()
StatelessElement.build(BuildContext context);
StatefulElement.build(BuildContext context);
ComponentElement.updateChild(Element child, Widget newWidget, Object newSolt){

}

//lib/src/widgets/framework.dart Element
//Element类
Element inflateWidget(Widget newWidget, Ojbect? newSolt){
	if(key is BlobalKey){
		Element newChild = _retakeInactiveElement(key, newWeiget);
		if(newChild != null){
			newChild._activieWidthParent(this, newSolt);
			Element? updateChild = updateChild(newChild, newWidget, newSolt);
			return updateChild;
		}
	}

	Element newChild = newWidget.createElement();
	newChild.mount(this, newSolt);
	return newChild;
}

//更新child
Element updateChild(Element child, Widget newWidget, Object newSolt) {
	if(newWidget == null){
		if(child != null) {
			deactivateChild(child);
		}
		return null;
	}

	Element newChild;
	if(child != null){
		bool hasSameSuperclass = true;
		if(hasSameSuperclass && child.widget == newWidget){
			if(child.solt != newSolt){
				updateSoltForChild(child, newSolt);
			}
			newChild = child;
		} else if(hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)){
			if(child.solt != newSolt){
				updateSoltForChild(newSolt);
			}
			child.update(newWidget);
			newChild = child;
		} else {
			deactivateChild(child);
			newChild = inflateWidget(newWidget, newSolt);
		}
	} else {
		newChild = inflateWidget(newWidget, newSolt);
	}
}

渲染流程

请求VSYN信息

核心方法:scheduleFrame()

请VSYNC信息触发场景

  • 调度器触发,如定时器、动画、滚动等
  • 页面启动、窗口变化等
  • 用户主动解决,setState

以setState为例

  • State.setState()
  • Element.markNeedsBuild()
  • BuildOwner.scheduleBuildFor(element);
    • onBuildScheduled();
  • WidgetsBinding._handleBuildScheduled();
  • SchedulerBinding.ensureVisualUpdate()
  • PlatformDispatcher.scheduleFrame()

------------------ 以下为C++ ------------------

  • PlatformConfigurationNaitveApi::scheduleFrame()
  • RuntimeController::ScheduleFrame();
  • Engine:ScheduleFrame();
  • Animator::RequestFrame();
  • Animator::AwaitVsync()
  • VsyncWaiter::AwaitVsync()

回调VSYNC

核心方法:BeginFrame()

请求SYNC信号后,由系统触发回调

  • Animator::BeginFrame();
  • Shell::OnAnimatorBeginFrame();
  • Engine::BeginFrame();
  • RuntimeController::BeginFrame();
  • PltformConfiguration::BeginFrame(),反射调用_beginFrame&_drawFrame

------------------ 以下为Dart ------------------

  • _beginFrame(flutter/lib/ui/hooks.dart)
  • PlatformDispatcher._beginFrame();
  • SchedulerBinding._handleBeginFrame();(在SchedulerBinding.ensureFrameCallbacksRegistered方法中建立绑定关系)
  • SchedulerBinding._handleDrawFrame();
// src/lib/rendering/binding.dart
//RendererBinding
void drawFrame() {
	pipelineOwner.flushLayout();
	pipelineOwner.flushCompositingBits();
	pipelineOwner.flushPaint();
    //进行layer合并,并将layerTree传递到C++进行渲染
	renderView.compositeFrame();
}

布局Layout

// src/lib/rendering/object.dart
//PipelineOwner
void flushLayout() {
	for( int i=0; i<dirtyNodes.length; i++){
		node._layoutWidthoutResize();
	}
}

//RenderObject
void _layoutWithoutResize(){
	performLayout();
	markNeedPaint();
}

//RenderView extends RenderObject
void performLayout(){
	if(child != null) {
		child.layout(BoxConstraints.tight(_size));
	}
}

//RenderBox extends RenderObject, 布局类RenderObject均继承RenderBox
void layout(Constraints constraints, {bool parentUsesSize = false}) {
	super.layout(constraints, parentUsesSize);
}

//RenderObject
void layout(Constraints constraints, { bool parentUsesSize = false }) {
	visitChildren();
	performLayout();
	markNeedsPaint();
}

//RenderObject
void markNeedsPaint(){
	if(isRepaintBoundary && _wasRepaintBoundary){
		pipelineOwner._nodesNeedingPaint.add(this);
		pipelineOwner.requestVisubleUpdate();
	} else if(parent is RenderObject){
		//parent哪来的?
		RenderObject parent = this.parent as RenderObject;
		parent.markNeedsPaint();
	} else {
		pipelineOwner.requestVisualUpdate();
	}
}

绘制Paint

//lib/src/rendering/object.dart
//PipelineOwner
void flushPaint() {
	for(RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => b.depth - a.depth)){
        if(node._needsPaint)
            PaintingContext.repaintCompositedChild(node);
        else
            PaintingContext.updateLayerProperties(node);
    }
}

----Render----
BindingBase.reassembleApplication();
RendererBinding.performReassemble();
RenderView.reassemble();

RenderObject.reassemble()

RenderObject.markNeedsPaint()
ower.requestVisualUpdate()(PipelineOwner)
RendererBinding 创建了 PipelineOwner,将ensureVisualUpdate赋值给onNeedVisualUpdate字段

----Widget-----
BuildOwner.reassemble();
Element.reassemble();
.markNeedsBuild();

获取Surface
获取Canvas

WidgetsBinding.drawFrame()
BuildOwner.buildScope()

PipelineOwner.flushLayout();
RenderObject._layoutWithoutResize();
RenderObject.performLayout()(RenderView)
RenderBox.layout(BoxConstraints.tight(_size));
RenderObejct.performLayout();

PipelineOwner.flushPaint();
RenderView.paint(PaintingContext context, Offset offset);
PaintingContext.paintChild();
RenderObject._paintWithContext();
RenderObject.paint()

自定义View
因为有Widget、Element、RenderObject3棵树,自定个View比较复杂
提前创建好了一个CustomPaint的Widget,有一个painter参数,暴露给用户来自定View样式。
painter类型CustomPainter

图像数据送显
RenderView.compositeFrame();

final ui.SceneBuilder builder = ui.SceneBuilder();
final ui.Scene scene = layer!.buildScene(builder);
_window.render(scene);
scene.dispose();

attachRootWidget()

更新
MyHomePageState extends State
State.setState();
Element.markNeedsBuild();
BuildOwner.scheduleBuildFor(element);
onBuildScheduled();

BuildOwner.onBuildScheduled()回调方法绑定发生在WidgetsBinding类,

WidgetsBinding._handleBuildScheduled();
ensureVisualUpdate,ensureVisualUpdate方法属于SchedulerBinding类,由WidgetsBinding 通过on 混入
scheduleFrame()
PlatformDispatcher.scheduleFrame()
_scheduleFrame(),由@FfiNative注解
@FfiNative()>(‘PlatformConfigNativeApi::ScheduleFrame’)
external static void _scheduleFrame();

Element挂载

Element.mount()

关联parent,设置solt、owner,并注册key。
关联parent时为何没有设置parent->child=this?
原因:parent.updateChild创建子Element时已经关联。

void mount(Element parent, Object newSolt){
	_parent = parent;
	_solt = newSolt;
	if(parent != null){
		_owner = parent.owner;
	}
	final Key key = widget.key;
	if(key is GlobalKey){
		_owner._registerGlobalKey(key, this);
	}
}

void rebuild({force = false}){
	performRebuild();
}

void performRebuild(){
	_dirty = false;
}

ComponentElement.mount()

自定的Widget要么继承StatelessWidget,要么继承StatefulWidget,它们均又继承自ComponentElement。
ComponentElement.mount()时,会触发重新rebuild()。

void mount(Element parent, Object newSolt){
	super.mount(parent, newSolt);
	_firstBuild();
}

void _firstBuild(){
	rebuild();
}

void performRebuild(){
	Widget built = build();
	super.performRebuild();
	_child = updateChild(_child, built, solt);
}

RenderObjectElement.mount()

RenderObjectElement在挂载时,会创建RenderObject,

void mount(Element parent, Object newSolt){
	super.mount(parent, newSolt);
	_renderObject = (widget as RenderObjectWidget).createRenderObject(this);
	attachRenderObject(newSolt);
	// clears the "dirty" flag
	super.performRebuild();
}

void performRebuild(){
	_performRebuild();
}

void _performRebuild(){
	//将Widget中的属性更新到RenderObject。更新RenderObject时,如果属性有变化,则将RenderObject添加到dirtyList中,重新渲染
	(widget as RenderObjectWidget).updateRenderObject(this, renderObject);
	//清除Element _dirty标记,也就是说Element在属性更新过程中的使命已经完成,接下来的操作交给RenderObject处理就可以了。
	super.performRebuild();
}

RenderObject挂载

RenderObject挂载在Element中完成。

// RenderObjectElement
void attachRenderObject(Object newSolt){
	_solt = newSolt;
	_ancestorRenderObjectElement = _findAncestorRenderObjectElement();
	_ancestorRenderObjectElement.insertRenderObjectElementChild(renderObject, newSolt);
}

// SingleChildRenderObjectElement
void insertRenderObjectElement(RenderObject child, Object solt){
	final RenderObjectWithChildMixin<RenderObject> renderObject = this.renderObject as RenderObjectWidthChildMixin<RenderObject>;
	renderObject.child = child;
}

// MultiChildRenderObjectElement
void insertRenderObjectElement(RenderObject child, Object solt){
	final ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>> renderObject = this.renderObject;
	renderObject.insert(child, after: solt.value?.renderObject);
}

rebuild

页面元素创建完毕,由点击等触发setState调用,从而触发Element.rebuild发生。
rebuild会调用performRebuild方法。
继承ComponentElement的元素(组合Element),会调用Widget/State的build()方法,重新创建一个Widget对象,来更新当前Element的child,或更新当前child.widget(Widget的build方法就是用来创建子Widget的)。
继承RenderObjectElement的元素(渲染Element),会调用RenderObjectWidget.updateRenderObject()将Widget的属性信息同步到RenderObject。同步过程,如果发现属性值有变化,则会调用RenderObject.markNeedsPaint()方法,标记当前RenderObject为脏元素,需要刷新。在VSYNC信号到来时,即可取得脏元素进行重新绘制。

//Element
void rebuild(){
	performRebuild();
}

//ComponentElement
void rebuild(){
	Widget built = build();
	_child = updateChild(_child, build, solt);
}

//Element
Element updateChild(Element child, Widget newWidget, Object newSolt) {
	//xxxx
	child.update(newWidget);
	//xxxx
}

update

//StatelessElement
void update(StatelessWidget newWidget){
	super.update(newWidget);
	rebuild({force:true});
}

//StatefulElement
void update(StatefulWidget newWidget){
	super.update(newWidget);
	StatefulWidget oldWidget = state._widget;
	state._widget = newWidget;
	state.didUpdateWidget(oldWidget);
	rebuild({force:true});
}

//SingleChildRenderObjectElement
void update(SingleChildRenderObjectWidget newWidget){
	super.update(newWidget);
	_child = updateChild(_child, (newWidget as SingleChildRenderObjectWidget).child, null);
}

//MultiChildRenderObjectElement
void update(MultiChildRenderObjectWidget newWidget){
	super.update(newWidget);
	MultiChildRenderObjectWidget multiChildRenderObjectWidget = widget as MultiChildRenderObjectWidget;
	_children = updateChildren(_children, multiChildRenderObjectWidget.children, forgottenChildren: _forgottenChildren);
	_forgottenChildren.clear();
}


Switch控件的RenderObject在更新属性时,将自己标记为_dirty。

//lib/src/cupertino/switch.dart
set activeColor(Color value) {
    assert(value != null);
    if (value == _activeColor) {
      return;
    }
    _activeColor = value;
    markNeedsPaint();
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter渲染机制可以从源码角度来理解。Flutter渲染与两个线程直接相关,分别是UI线程和GPU线程。UI线程负责执行Dart root isolate代码,并将其转换为Layer tree。 Layer 是 Flutter Framework 中的一个重要概念,它代表了一块矩形区域,可以包含图形、文本、图片等内容。这些 Layer 最终会被提交到 Engine 中进行绘制。 Layer 的工作原理是将所有的绘制操作转化为一系列的绘制指令,然后将这些指令传递给 GPU 线程进行绘制。 Flutter Framework 中的绘制过程经过多个步骤,包括布局、绘制、合成等,最终将所有的 Layer 组合在一起形成最终的界面。通过理解 Flutter渲染原理,开发者可以更清晰地了解应用程序的渲染过程,并进行性能优化。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Flutter渲染机制—UI线程](https://download.csdn.net/download/weixin_38550834/15446392)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Flutter 画面渲染的全面解析](https://blog.csdn.net/chengjiamei/article/details/107974790)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值