HarmonyOS APP实战-画图APP - 第14篇:可变帧率与性能优化

发布时间:2026/11/5 13:43:24

HarmonyOS APP实战-画图APP - 第14篇:可变帧率与性能优化 HarmonyOS APP实战-画图APP - 第14篇使用displaySync定制绘制帧率开篇上一篇我们完成了本地数据库存储与读取功能通过关系型数据库RdbStore保存了画作元数据名称、创建时间、缩略图路径并实现了画作列表页面支持从列表加载已有画作继续编辑。数据库模块是画图APP的数据持久化基石。本篇将聚焦性能优化——根据绘制内容的复杂度动态调整绘制帧率。画图APP在画笔手绘时需要高帧率60fps保证跟手性而空闲状态或显示静态图形时可以降低帧率至30fps以减少功耗。HarmonyOS提供了displaySyncAPI允许开发者针对自绘制内容指定不同的目标帧率。我们将封装一个FrameRateController模块并在DrawingCanvas组件中集成它实现按需切换帧率。核心实现基础配置导入与常量定义首先在模块顶部导入displaySync并定义帧率常量。// FrameRateController.etsimport{displaySync}fromohos.graphics.displaySync;/** * 帧率常量 */exportconstFRAME_RATE_HIGH60;// 高帧率模式画笔绘制时exportconstFRAME_RATE_LOW30;// 低帧率模式静止或浏览时关键点说明ohos.graphics.displaySync是ArkGraphics 2D提供的可变帧率能力模块。帧率值单位是fps帧每秒60fps适合手绘追踪30fps满足静态显示且降低功耗。核心逻辑FrameRateController类FrameRateController负责创建和管理DisplaySync实例并根据业务状态设置目标帧率。// FrameRateController.etsexportclassFrameRateController{privatedisplaySyncInstance:displaySync.DisplaySync|nullnull;privateisRunning:booleanfalse;privatecurrentRate:numberFRAME_RATE_LOW;/** * 初始化DisplaySync实例 * param requestId 请求标识用于区分不同绘制场景 */publicasyncinit(requestId:string):Promisevoid{if(this.displaySyncInstance){return;}try{this.displaySyncInstanceawaitdisplaySync.create(requestId);console.info(FrameRateController: DisplaySync created with requestId${requestId});}catch(err){console.error(FrameRateController: create failed, error${JSON.stringify(err)});}}/** * 启动帧率控制 * param frameCallback 每帧回调参数为时间戳 */publicstart(frameCallback:(timestamp:number)void):void{if(!this.displaySyncInstance||this.isRunning){return;}this.displaySyncInstance.start(frameCallback);this.isRunningtrue;console.info(FrameRateController: started);}/** * 停止帧率控制 */publicstop():void{if(!this.displaySyncInstance||!this.isRunning){return;}this.displaySyncInstance.stop();this.isRunningfalse;console.info(FrameRateController: stopped);}/** * 更新目标帧率 * param rate 新的帧率值fps */publicupdateFrameRate(rate:number):void{if(!this.displaySyncInstance){console.warn(FrameRateController: instance not initialized);return;}try{this.displaySyncInstance.setExpectedFrameRate(rate);this.currentRaterate;console.info(FrameRateController: frame rate updated to${rate}fps);}catch(err){console.error(FrameRateController: setExpectedFrameRate failed, error${JSON.stringify(err)});}}/** * 销毁DisplaySync实例 */publicdestroy():void{if(this.displaySyncInstance){this.displaySyncInstance.destroy();this.displaySyncInstancenull;this.isRunningfalse;console.info(FrameRateController: destroyed);}}/** * 获取当前帧率 */publicgetCurrentRate():number{returnthis.currentRate;}}关键点说明displaySync.create(requestId)是一个异步方法返回PromiseDisplaySync实例。setExpectedFrameRate(rate)设置期望帧率系统会尽量按照该值调度。start(callback)开始帧率控制回调参数为时间戳纳秒可用于驱动动画循环。destroy()释放资源在页面销毁时调用。实际项目中帧率回调可以作为绘制驱动的定时器替代setInterval或requestAnimationFrame提供更精确的帧同步。完整模块集成到DrawingCanvas组件DrawingCanvas是画图APP的核心绘制组件。我们在其中集成FrameRateController在触摸开始/移动时切换到高帧率触摸结束或闲置时降回低帧率。同时为了兼容原有绘制逻辑我们将帧率回调绑定到画布重绘操作。// DrawingCanvas.ets简化版仅展示集成逻辑import{CanvasRenderingContext2D}fromohos.graphics.ui;import{FrameRateController,FRAME_RATE_HIGH,FRAME_RATE_LOW}from./FrameRateController;import{Point,DrawCommand}from../model/DrawCommand;// 假设自定义模型Componentexportstruct DrawingCanvas{privatesettings:RenderingContextSettingsnewRenderingContextSettings(true);privatecontext:CanvasRenderingContext2DnewCanvasRenderingContext2D(this.settings);privateframeCtrl:FrameRateControllernewFrameRateController();privateisDrawing:booleanfalse;privatelastTouch:Point{x:0,y:0};// ... 其他属性aboutToAppear(){// 初始化DisplaySyncrequestId可自定义this.frameCtrl.init(drawing_canvas_main).then((){// 启动帧率控制将回调连接到画布刷新this.frameCtrl.start((timestamp:number){// 这里可以驱动持续的绘制更新例如动画// 对于手绘我们只在触摸事件中局部重绘此回调暂不开启批量重绘// 但保持帧率控制活跃});// 初始设为低帧率this.frameCtrl.updateFrameRate(FRAME_RATE_LOW);});}onTouch(event:TouchEvent){if(!this.frameCtrl)return;switch(event.type){caseTouchType.Down:this.isDrawingtrue;// 触摸开始时切换到高帧率保证跟手this.frameCtrl.updateFrameRate(FRAME_RATE_HIGH);this.lastTouch.xevent.touches[0].x;this.lastTouch.yevent.touches[0].y;// 开始新路径this.startNewPath(this.lastTouch);break;caseTouchType.Move:if(this.isDrawing){constcurrent{x:event.touches[0].x,y:event.touches[0].y};// 添加点到当前路径并绘制this.addPointToPath(current);this.lastTouchcurrent;}break;caseTouchType.Up:caseTouchType.Cancel:// 绘制结束恢复低帧率if(this.isDrawing){this.finishPath();this.isDrawingfalse;this.frameCtrl.updateFrameRate(FRAME_RATE_LOW);}break;}}privatestartNewPath(point:Point):void{// 原有逻辑开始一个新的Path}privateaddPointToPath(point:Point):void{// 原有逻辑向Path增加点并调用context.drawPath()}privatefinishPath():void{// 原有逻辑结束路径并保存到历史}aboutToDisappear(){this.frameCtrl.stop();this.frameCtrl.destroy();}build(){Canvas(this.context).width(100%).height(100%).onTouch((event:TouchEvent)this.onTouch(event))}}议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_urlplaceholder.pngpos_idimg-K54aM3fo-1783906018434)关键点说明aboutToAppear中初始化FrameRateController并启动默认低帧率。在onTouch的Down事件中更新为高帧率Up或Cancel时恢复低帧率。注意帧率回调本身不涉及重绘但保持start可以让系统按照目标帧率调度实际绘制仍由触摸事件触发。aboutToDisappear中停止并销毁实例防止内存泄漏。如果后续需要实现动画绘制如动态渐变、粒子效果可以利用frameCallback的时间戳驱动逐帧重绘此时帧率控制效益更明显。运行验证在画图APP中打开任意画布文件或新建画布用手指在画布上绘制当手指按下并移动时CPU/GPU会按60fps渲染轨迹体验流畅跟手。当手指抬起后帧率会降为30fps此时进行菜单操作或查看静态内容手机功耗降低。开发者可以通过DevEco Studio的Profiler工具查看帧率变化运行APP点击“性能分析”在“帧率时间线”中观察绘制时段帧率约60fps闲置时段约30fps。如果未看到切换请确认displaySync已正确初始化和权限设置无需额外权限。另外模拟器可能不完全支持帧率动态调节建议在真机上测试。小结与预告本篇实现了画图APP的帧率动态调节功能通过FrameRateController模块封装displaySyncAPI根据绘制活动自动切换60fps和30fps在保持手绘跟手性的同时减少闲置功耗。该模块是性能优化的重要一环可直接复用至其他自绘制场景。下一篇《使用overdraw工具检测性能》将介绍如何利用HarmonyOS的过度绘制调试工具Overdraw Debug分析画布绘制效率识别冗余绘制层次并通过Canvas的clip、clearRect等技术优化绘制指令进一步提升流畅度。
延伸阅读

更多相关文章

2026/10/30 22:26:26

HarmonyOS APP实战-画图APP - 第12篇:离线图像处理与保存

HarmonyOS APP实战-画图APP - 第12篇&#xff1a;导出与加载图片文件 1. 开篇 上一篇我们完成了操作历史管理模块&#xff0c;实现了基于命令模式的撤销/重做栈&#xff1a;HistoryManager 类维护了两个 Stack<Command> 实例&#xff0c;每次绘制操作封装为 Command 对象…

2026/10/28 23:50:14

2026年多商户商城系统哪个好?商家入驻、分账和权限对比

2026年多商户商城系统哪个好&#xff1f;商家入驻、分账和权限对比多商户商城系统哪个好&#xff0c;不能只看能不能上架商品。平台型业务和单店商城不一样&#xff0c;核心在商家能不能入驻&#xff0c;平台能不能审核商品&#xff0c;订单和售后责任怎么划分&#xff0c;平台…

2026/11/4 21:15:46

育儿专题(3)疫苗

目录 1&#xff0c;国家免疫规划疫苗儿童免疫程序表 2&#xff0c;详细疫苗规划 &#xff08;0&#xff09;背景&#xff08;必读&#xff09; &#xff08;1&#xff09;卡介苗&#xff08;出生&#xff09; &#xff08;2&#xff09;甲肝、乙肝、2联&#xff08;出生、…

2026/11/5 13:25:11

基于ADS122U04IPWR与STM32F427ZI的工业测温方案设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 13:20:10

Dubbo服务下线实时告警:基于ZooKeeper Watch的轻量级监控方案

简介&#xff1a;这是一套面向Java分布式系统运维与开发人员的Dubbo服务高可用监控解决方案&#xff0c;聚焦于Provider异常下线的实时感知与告警响应。资源通过Zookeeper监听机制实现服务状态变更捕获&#xff0c;结合邮件通知模块&#xff0c;在不侵入原有Dubbo代码的前提下&…

2026/11/5 13:20:10

SSM超市管理系统源码解析:从分层架构到本地部署与业务修改

简介&#xff1a;这份资源是面向高校计算机专业学生与Java初学者的一套SSM框架课程设计完整项目&#xff0c;围绕超市管理场景&#xff0c;帮助读者完成从框架整合到业务模块落地的实战练习&#xff0c;适合作为毕业设计或课程作业的参考方案。压缩包共792个文件&#xff0c;约…

2026/11/5 13:20:10

SSM超市管理系统实战:从课设跑通到二次开发全解析

简介&#xff1a;这份资源是面向高校计算机相关专业学生与Java入门开发者的SSM课程设计参考项目&#xff0c;围绕超市管理场景&#xff0c;解决商品、库存、销售等业务模块从设计到落地的实践需求&#xff0c;适合作为课程作业、毕业设计原型或SSM框架练手案例。压缩包共792个文…

2026/11/5 13:15:07

PIPE4.3.0安装排错:JDK版本、JAVA_HOME与Petri验证

简介&#xff1a;PIPE 4.3.0 是一款基于 Petri 网的图形化建模与仿真软件&#xff0c;面向软件工程、系统分析与教学实验场景&#xff0c;帮助读者完成并发、同步与竞争等系统行为的建模、动态仿真及性质分析。压缩包共 2391 个文件&#xff0c;约 28.43MB&#xff0c;包含大量…

2026/11/5 13:15:07

用栈实现队列:双栈结构与工程实践

1. 栈与队列的相爱相杀第一次看到这个题目时&#xff0c;我正坐在星巴克啃着牛角包。用栈实现队列&#xff1f;这就像用筷子喝汤——不是不行&#xff0c;但总觉得哪里怪怪的。栈和队列这对数据结构里的欢喜冤家&#xff0c;一个后进先出&#xff08;LIFO&#xff09;&#xff…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代&#xff0c;基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而&#xff0c;与配合度高的人类不同&#xff0c;宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态&#xff0c;更无法控制光照环境。实际应用中&#xff0c;我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时&#xff0c;Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门&#xff0c;我先说个结论&#xff1a;这事真不难&#xff0c;难的是资料太散、路线太多&#xff0c;今天这个框架明天那个工具&#xff0c;新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师&#xff0c;我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码&#xff0c;在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代&#xff0c;基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而&#xff0c;与配合度高的人类不同&#xff0c;宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态&#xff0c;更无法控制光照环境。实际应用中&#xff0c;我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑