点击响应优化
一、响应优化概述
响应(Response)是指应用在运行中,由用户直接或间接做出一个行为请求,当程序接受了该请求,随即做出一系列运算,最终界面发生变化的过程。简单来说,即用户发出指令,程序执行,设备显示变化。
在应用生态高速发展的背景下,虽然移动设备的硬件运算性能已经达到了新的高度,但与此同时应用研发者也设计出更加多元化、智能化的产品,展现样式百花齐放,这些产品对高性能的需求与日俱增,加上同类型相近功能的产品互相竞争,用户也会对App产品质量的要求越来越高,对响应速度的要求也愈加严格。
二、优化的具体方法
1、UI优化
从UI布局渲染角度,加快应用绘制性能,比如减少布局嵌套,减少元素渲染,缓存UI动效等。
2、按需加载优化
根据界面展示或模块加载的需要,延迟加载相关内容,从而减少对首帧页面的性能消耗。
3、并发优化
使用系统并发执行多个任务的能力,减少响应过程中任务执行的整体时间。
4、IPC通信优化
针对IPC通信特点,尽量减少不必要的通信次数和数据体积,防止IPC通道影响界面响应。
5、逻辑优化
在相关生命周期中减少冗余、降低耗时,提升执行效率,包括善用数据结构、缓存、优化调整时序等。
6、视觉感知优化
通过交互设计的优化,利用动效动画的形式,在视觉层面提升用户响应速度的感知。
三、分析工具
影响点击响应性能的因素有很多,借助DevEco Studio集成的相关分析工具,可以收集大量的系统数据,自动执行重复任务,建立统一的优化标准和流程,减少个人差异和误操作的可能性,帮助开发人员更好地了解性能瓶颈和优化潜力。在分析优化的过程中,可能用到以下工具中的一个或多个。
1、AppAnalyzer
AppAnalyzer是DevEco Studio中提供的检测评分工具,用于测试并评价HarmonyOS应用或元服务的质量,能快速提供评估结果和改进建议,当前支持的测试类型包括兼容性、性能、UX测试和最佳实践等,其中点击操作响应是性能类型中的一项检测规则,开发者可以使用该工具检测响应性能。
2、Profiler Frame
Profiler是DevEco Studio提供的场景化调优工具,其中Frame可以帮助开发者深度分析性能问题,通过录制应用运行过程中的关键数据,从而识别卡顿丢帧、耗时长等问题的原因所在。
3、ArkUI Inspector
ArkUI Inspector是DevEco Studio中提供用于检查UI的工具,开发者可以借助它预览真机或模拟器中的UI效果,快速定位布局层级问题,也可以观察组件属性、不同组件之间的关系等。
四、UI优化
应用开发中的用户界面UI(User Interface)是用户与应用程序交互的关键部分。使用不同类型的布局,能在界面显示上达到预期效果,甚至某些方式能将页面排布得更加美观,但也容易引入不合理的结构问题,如果UI界面中存在过度的布局计算,冗余的元素绘制,将会带来设备资源的大量开销,造成响应性能的衰退。
1、减少嵌套层级
布局的嵌套层次过深会导致在创建节点及进行布局时耗更多时间。因此开发者在开发时,应避免冗余的嵌套,并尽量使用扁平化布局来优化嵌套层级。
2、减少渲染时间
if/else条件渲染是ArkUI应用开发框架提供的渲染控制能力,可根据应用的不同状态,渲染对应分支下的UI描述。
3、用renderGroup缓存动效
页面响应时,可能大量使用属性动画和转场动画,当复杂度达到一定程度之后,就有可能出现卡顿的情况。renderGroup是组件通用方法,它代表了渲染绘制的一个组合。
五、按需加载优化
1、LazyForEach懒加载
使用LazyForEach懒加载替换ForEach,避免像ForEach那样一次性初始化和加载所有元素,从而使首帧绘制时创建列表元素时间大大减少,提升响应性能表现。
2、动态import
动态import是一种模块加载机制,允许应用程序在运行时按照实际需求去加载相关模块。在某些条件满足时(比如用户交互时,或ABTest分支切换时)再加载特定模块,可以减少初始化import的加载时间和资源消耗,这将有助于提高应用程序的内存性能和响应速度。
与静态import不同,动态import仅在需要时才消耗CPU等资源;相比静态import在编译时就确定了引入的所有模块,动态import还有更佳的语法灵活性,借助这种灵活,能够实现编码和路由级别的粒度分割,优化模块层次的懒加载性能。
六、并发优化
并发是指多个任务在同一个时间段内同时触发执行,具体逻辑中使用多线程异步执行,与之相对的概念是串行任务,按顺序同步执行。
应用中的并发优化就是在响应用户操作期间,尽可能地让主线程只执行UI绘制相关的任务,而将非UI的耗时任务分配给其他线程或者延迟处理。这样借助多线程的异步技术,充分利用多核处理器的能力,提高应用程序的并发处理能力,减少用户等待时间,保证用户界面的响应流畅性。
1、异步任务并发处理
使用多线程并发能力进行开发的过程中,主要实现方式有:
- 利用TaskPool执行简单并行任务:将一些耗时的操作放入异步任务中处理,避免阻塞主线程,提升应用的响应速度;
- 利用Worker完成周期类耗时操作:Worker可以空跑在后台等待事件触发,周期触发耗时操作使用Worker,这样可以避免TaskPool频繁拉起影响性能。
2、使用组件异步加载特性
Image组件支持异步加载特性:当应用在页面上展示一批图片的时候,会先显示空白占位块,当图片在其他线程加载完毕后,再替换占位块。这样图片加载就可以不阻塞页面的显示,给用户带来良好的交互体验。
七、减少调用数据库API次数
数据库是存储和管理数据的工具集合。通过系统框架封装的API,可以对数据及其结构进行访问、管理、增添或更新等一系列操作。
通常来讲,数据库的调用会比较耗时,常见的增、删、改、查等都提供了异步接口,合理使用这些接口不会对响应性能产生影响。
然而一些同步API,因为调用频率较高,反而成为响应时的性能瓶颈。
比如:ResultSet的getColumnIndex,其作用是根据指定的列名获取列索引,getColumnIndex执行的耗时大约只是几十微秒的量级,但如果在循环查询数据条目时,每次都重复调用了getColumnIndex,最终的耗时=数据条数*获取索引耗时,当查询数据量大的表时,总开销并不低。
那么优化的方法就是减少调用该API的次数。因为同一数据表在结构确定后,相应字段的index索引不会变化 ,所以提前缓存index索引值,将getColumnIndex调用提取到循环体外,避免重复调用,可以减少耗时。
八、IPC通信阻塞优化
操作系统提供IPC(Inter-Process Communication,进程间通信)机制进行跨进程通信。需要跨进程通信的原因是因为每个进程都有自己独立的资源和内存空间,其他进程不能随意访问不同进程的内存和资源。当工作进程需要获取其他进程的数据或能力时,就要使用IPC的通信能力。而IPC过程会消耗一定的系统资源 ,受限于实现底层机制,单位时间内传输的数据量是受限的,短时间内频繁IPC,有可能产生通信阻塞。
目前系统有三种情况应用了IPC的通信能力:
- 调用涉及IPC的API,比如WIFI、蓝牙、NFC等模块中的同步接口。
- 使用@ohos.rpc模块开发实现跨进程通信的能力。
- 后台服务:通过IPC机制提供跨进程的服务调用能力,实现一个后台服务并对外提供相应的能力。
优化角度:
本地缓存数据:合理使用本地缓存,将常用的数据存储在本地,而不是每次都通过IPC请求。这样可以减少不必要的通信次数。确保缓存数据的有效期和更新策略是合理的,以防止缓存数据过期或不一致。
批处理请求:将多个IPC请求合并成一个批处理请求,从而减少通信的次数。这对于频繁的小数据请求尤其有用。
异步处理:对于不需要立即响应的IPC请求,可以将它们设置为异步处理,以免阻塞主线程。
减少不必要的数据传输:确保只传输应用所需的数据,避免传输不必要的信息
九、逻辑优化
逻辑的优劣对应用响应速度的影响是比较明显的,特别是点击切换后新页面中的aboutToAppear、onPageShow等生命周期回调,以及点击操作页面中的aboutToDisappear等,需要充分优化编码、减少冗余、避免耗时,提升执行效率。
基于平台SDK的开发框架下,对App生命周期的理解,可以帮助开发人员识别程序在不同阶段的行为,弄清楚不同形态转换时触发的接口性质、各函数被调用的频率,进而挖掘出编码优化的方向。
1、选择合适的数据结构
索引存取考虑使用array数组,hash查找考虑使用map,去重逻辑考虑使用set等;
有时开发者使用object变量作为容器去处理map的逻辑,可以考虑使用ArkTS提供的高性能容器类,直接使用HashMap;
遇到纯数值计算的场合,推荐使用TypedArray的数据结构,比如Int8Array、Int32Array、Float32Array、BigInt64Array等。
2、合理使用缓存
当某些运算结果会反复使用时,以空间换时间,提前缓存以便于下次调用
3、注意对象new和delete的频率
new和delete可能会触发内存管理回收,占用CPU资源从而影响界面渲染的能力,需要根据情况调整其频次。尤其在循环中,频繁的new、delete更会带来恶化的性能表现,应该尽量将new/delete优化到循环外去处理。
4、延迟执行资源释放操作
将资源关闭和释放操作放在setTimeout函数中执行,使其延迟到系统相对空闲的时刻进行,可以避免在程序忙碌时段占用关键资源,提升整体性能及响应能力。
5、减小拖动识别距离
应用识别拖动手势事件时需要设置合理的拖动距离,设置不合理的拖动距离会导致滑动不跟手、响应时延慢等问题。针对此类问题可以通过设置distance大小来解决。
十、视觉感知优化
上述几节内容,是从减少时延绝对值的角度来提升响应体验,而视觉感知优化则是通过交互设计的优化,提升用户响应速度的感知。
从响应速度的反面角度来讲,应用的卡顿其实就是视觉上出现了不流畅的画面,引起了用户的注意,令其产生了一定的不适感。这也就意味着,在用户操作后,需要第一时间从视觉层面给与反馈响应,从而解决视觉动作带来的不适。
我们可以在用户的交互动作开始时,从感知角度添加一些动画元素,比如单击效果、转场缩放、加载进度条、共享动画等,这些可以告诉用户目前状态发生了变化,APP在快速地运作着;而动画的背后是:数据的计算,布局的渲染,内容的加载等等,当新界面渲染显示完成,上述动画元素就可通过渐变消失、移出屏外等友好的方式退出视觉区域。
使用这样连贯的感知元素,能提供一种视觉隐喻,将用户的注意力从上个页面平滑地过渡到下个页面;交互动画表现得友好、有趣和实用,则用户在响应侧的体验会更加舒适,从主观上也会认为应用性能好、反应速度快。
十一、优化处理原则
- 充分复用,减少UI绘制任务,移除冗余
- 延迟处理,延后处理不紧要任务
- 使用并发,充分利用CPU多核性能
- 利用缓存,采用合适的数据结构,合理的逻辑顺序
- 善用动画反馈,增强用户直观感受