鸿蒙系统进一步学习(二):ArkUI底层原理揭秘

在笔者写文章的时候,鸿蒙6.0发布了,鸿蒙PC也在大家的呼唤中如期而至,在体验过鸿蒙新系统之后,都有一个感慨:流畅,比肩iOS的流畅。那么为什么那么流畅呢?这个就需要从ArkUI的底层渲染原理说起了。

1 基础概念介绍

在解释渲染原理之前,首先需要公知几个通用的知识点。当用户使用手机的时候,会进行一系列的点触操作,页面也会随之变化,有的是全局变化,有的局部变化,如果它的变化过程衔接的非常丝滑,用户就会感觉流畅,反之就会有不灵敏,卡顿的感觉。

1.1 整体流程

抛开所有束缚,读者可以和笔者一起思考,如果要把一个页面渲染出来,大致要经历几个比较大的步骤?笔者粗略的认为需要5个主要步骤,如图1所示。

图1 渲染的主要步骤示意图

1)渲染信号

这个是第一个核心的前提,因为页面它不会自己刷新,它需要等待一个信号来才启动刷新的动作,如果因某些原因信号未到达,即使用户反馈点触屏幕也不会刷新,这通常被称为死机,在后面的章节会介绍,鸿蒙里面这叫做AppFreeze,此时整个程序出了问题。所以正常刷新的第一步,一定是渲染信号的正确到来。

2)前期工作

这个所谓的前期工作,是因为它的细节步骤太多,比如一个控件有哪些变化,是增加的动画,还是增加了事件监听等,因为他们都会影响后面的步骤,所以必须前置。

3)测量

这个是步骤的目的是测量每个控件的大小,比如一个按钮,它多宽多高,这个涉及到开发者代码里面的设置,如果用ArkTS的视角,width设置为固定宽度,那这一步就给它一个固定宽度即可;如果设置的是可变的,比如50%的宽度,则需要获取父控件的宽度后,再进行自身宽度的赋值;如果设置的是随字体变化而变化的宽度,则需要获取所承载字体的宽度后,再根据padding值计算本身的宽度。同理,高度也是一样。综上所述,测量的目的就是确定空间的大小,也就是宽和高。

4)布局

如果说第三步是确定空件的宽高,那么本步就是确定空件的位置,即放在哪里?如果整体的父布局是纵向线性布局,那么自己就应该放兄弟节点的下面,如果父布局设置了间距,那么自身的最高位置,就是兄弟节点的最低位置加上父控件的间距值。同理如果是横向节点,就靠着最右边放,如果是弹性布局或者列表布局,就要根据父布局的计算规则来计算自身的位置。综上所述,本步骤执行完后,就知道自己应该放哪里了。

5)渲染

这一步就是交给渲染组件去渲染了,比如一个简单的按钮,在确定了大小和位置后,会根据这个按钮的背景色是绘制对应的颜色,然后再根据字体大小和颜色,去绘制字体,这些都是渲染线程去渲染即可。而渲染的前提就是前面这些数值都需要经过上述几个步骤,全部计算好。

通过这些步骤可以看出,每个步骤的职责都很明确,只做非常聚焦的事情,而他们的前后顺序也必须严格,不能颠倒,所以一般不允许在子线程里操作UI,以防止步骤紊乱导致的不可预知的问题。

2. 刷新率

相信读者或多或少都听过几个名字,120Hz高刷屏,60Hz屏幕这类的名词。iPhone直到iPhone17开始标准版才配备120Hz高刷屏,之前都是被嘲笑屏幕配置较低,那么刷新率到底和页面的渲染有什么关系呢?

对于屏幕来说,刷新率越高,人眼的观感就会越好,看习惯了高刷屏,再看低刷屏总感觉顿顿的。所谓的60Hz屏幕,意味着该屏幕在1秒钟之内最高可以刷新60次,而120Hz的屏幕则是1秒内可以刷新120次,所以一秒内的刷新频率越高,给人肉眼的感觉就是丝滑流畅,尤其在电竞游戏、电影和快速滑动列表的场景;但是对于读书,看图片的场景影响就会小很多。同时,120Hz的刷新率会增加屏幕的功耗,这个也很好理解,因为1秒钟内的工作次数比传统屏幕多了一倍。

而高刷新率屏幕对系统的挑战就比较大了,原来60Hz的屏幕,页面只要每隔16.6ms完成一次刷新就可以了,但是对于120Hz的屏幕,页面只有8.3ms的处理事件,也就是8.3ms之内完成不了,用户就会产生一定的顿挫感。它们的关系如图2所示。

图2 刷新率与每一帧处理时间变化图

所以要完成这种蜕变,有了很多的处理方式,

1)配备更强的处理芯片:该方式同时也会带来更高的功耗,如果性能想提升,功耗还想下降的话,就只能从芯片制程上下手,比如常见的3mn工艺、2mn工艺。

2)动态刷新:根据实际情况调整刷新率,对于普通的页面还是使用60Hz的刷新,甚至静态页面的时候更低。

3)更优秀的渲染机制:通过各种优化方式,把原来要16ms完成的步骤,降低到8.3ms以内,这个就会涉及到重构底层的渲染机制了。Android最新推出的Compose、谷歌跨平台解决方案Flutter以及ArkUI,都是这种思路。

3. 全局变化和局部变化

这个就比较好理解了,全局变化就是整个页面都发生了变化,比如游戏场景、列表快速滑动场景和电影场景,这个的特点就是全部页面的元素都要刷新,不存在太多相似元素;而局部变化就是整个页面只有一小块发生了变化,其它地方不变,比如按钮的字体和颜色发生了变化,它的特点是大部分元素不变的。

游戏或者电影样的场景,都不会用控件变化去做,是一套独立的渲染体系,比如使用OpenGL去渲染,需要对机型单独调试,不断优化底层代码才行,所以有些游戏,在某些机型上可以使用120Hz,有些却不行,这个和硬件本身的能力和软件的优化息息相关。

综上所述,如果想要更加丝滑流畅的用户体验,需要首先了解整体的页面渲染流程,可以从每个流程中去优化时间,当然提高本身的硬件也是不可或缺的方式,而ArkUI的思路是对于页面组件的刷新,大部分属于局部刷新的逻辑,所以可以使用差渲染的逻辑,不需要每次在每次刷新信号来了之后,就把整个页面都刷新一次,计算出差分的节点,仅仅对这些节点,进行局部进行刷新即可。其示意如图3所示。

图3 局部刷新示意图

对于按钮,由于自己的字体变化引发了按钮的变化,但是只改变了长度,所以只刷新了按钮所在的父布局即可,这就带来了好处,只刷新按钮区域,减少了整体的计算量,大大节省了计算大小和渲染的时间,同时了解这个原理后,读者应该能想到,在后期应用开发的布局中,应该如何写,才能让控件的刷新范围最小,在写应用的时候,脑袋中要实时地思考这个问题,这样写出来的应用会更加地丝滑流畅。

那么差分渲染的原理是什么呢?下个章节再详细讲诉

相关推荐
燐妤1 小时前
前端HTML编程2:深入学习表单与表格
前端·学习·html5
木斯佳1 小时前
HarmonyOS 本地存储实战:用一个记账本案例吃透 RDB 与 KVStore
harmonyos·存储
苗俊祥1 小时前
纯AI打造沐界输入法--简洁、流畅、实用的 HarmonyOS 中文输入法
华为·harmonyos
疯狂成瘾者1 小时前
Docker的学习路线
学习·docker·容器
for_ever_love__1 小时前
UI学习:UITableViewCell的创建及复用机制
学习·ui·objective-c
小成Coder2 小时前
【Jack实战】如何给《时光旅记》接入跨设备拍照和跨设备相册导入
华为·harmonyos·鸿蒙·码上创新
随风,奔跑2 小时前
Mybatis-Plus学习笔记
java·笔记·学习·mybatis
maaath2 小时前
【maaath】Flutter for OpenHarmony 集成应用更新能力
flutter·华为·harmonyos
key_3_feng2 小时前
鸿蒙6.0 Widget服务卡片落地方案
华为·harmonyos