如何使用 Choreographer 进行帧率优化
Choreographer
是 Android 提供的一个工具类,专门用来协调 UI 帧的渲染。你可以通过 Choreographer
来精确控制帧的绘制时机,以优化帧率,确保应用的流畅度。以下是如何使用 Choreographer
进行帧率优化的详细步骤:
1. 理解 Choreographer 的基本概念
- Choreographer#doFrame() 回调:
Choreographer
会在每次屏幕刷新时调用doFrame()
,你可以通过它在每个 VSYNC 信号到达时执行 UI 更新操作。它确保你的任务在帧间隔内完成,从而防止掉帧。 - VSYNC 信号:手机屏幕以固定频率刷新(通常是 60Hz,对应每 16ms 刷新一次)。
Choreographer
基于这个周期触发doFrame()
回调。
使用 Choreographer
可以保证绘制任务在每次屏幕刷新时得到调用,避免不必要的重复绘制,从而达到帧率优化的目的。
2. 如何使用 Choreographer 进行帧率优化
1. 设置 Choreographer.FrameCallback
回调
首先,你需要为 Choreographer
设置一个 FrameCallback
,并在每个 VSYNC
信号到达时执行自定义的 UI 更新逻辑。
Choreographer choreographer = Choreographer.getInstance();// 创建帧回调
Choreographer.FrameCallback frameCallback = new Choreographer.FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {// 在这里执行UI更新或动画逻辑updateUI();// 再次请求下一帧choreographer.postFrameCallback(this);}
};// 开始监听帧的回调
choreographer.postFrameCallback(frameCallback);
在 doFrame()
方法中,frameTimeNanos
参数表示当前帧的时间戳,单位是纳秒。
2. 执行 UI 更新或动画
在 doFrame()
回调中执行动画更新或者复杂的 UI 计算时,可以确保任务只在屏幕刷新时才运行,这样避免了过度渲染或无效的计算,从而节省 CPU 资源。例如:
private void updateUI() {// 更新视图的位置或动画状态imageView.setTranslationX(newXPosition);imageView.setTranslationY(newYPosition);// 请求重新绘制imageView.invalidate();
}
3. 确保帧率稳定(每 16ms 执行一次更新)
每次 VSYNC
信号间隔是 16ms (在 60Hz 刷新率的设备上),你的任务应该在这个时间内完成。通过 Choreographer
,你可以确保你的 UI 更新逻辑精确地同步到每个刷新周期,而不会频繁或者延迟执行。
3. 如何优化掉帧问题
1. 减少主线程负载
主线程在每一帧(16ms)内需要完成一系列任务(如测量、布局、绘制等)。如果任务超过 16ms 的时间限制,Choreographer
无法按时渲染新帧,就会导致掉帧问题。你可以采取以下措施来优化帧率:
- 将耗时任务移到后台线程:避免在
doFrame()
回调中执行耗时的操作,例如网络请求、数据库操作或文件读取。这些任务应放在后台线程中完成,然后通过Handler
或post()
方法将结果传递回主线程更新 UI。
new Thread(new Runnable() {@Overridepublic void run() {// 耗时操作final String result = performHeavyTask();// 在主线程上更新UInew Handler(Looper.getMainLooper()).post(new Runnable() {@Overridepublic void run() {updateUIWithResult(result);}});}
}).start();
2. 优化布局和绘制
-
减少布局嵌套:深层次嵌套的布局会导致更长的测量和布局时间。尽量使用扁平化的布局,减少嵌套视图。
-
优化绘制逻辑:如果你有自定义绘制逻辑,确保只绘制需要更新的部分。尽量避免在每帧中重新绘制整个视图,使用
invalidate(Rect dirty)
仅重绘发生变化的区域。
3. 使用 View.postOnAnimation()
优化动画
如果你在处理动画时手动更新视图位置,使用 View.postOnAnimation()
方法可以确保动画在屏幕刷新时执行,而不是在每个循环中不断请求重新绘制。
view.postOnAnimation(new Runnable() {@Overridepublic void run() {// 更新动画状态view.setTranslationX(newPositionX);// 再次请求下一帧view.postOnAnimation(this);}
});
postOnAnimation()
保证在每次屏幕刷新时执行动画更新,而不是浪费 CPU 资源在无效的帧上。
4. 监控帧率
在调试性能时,你可以通过 Android Profiler 或 Perfetto 来监控应用的帧率,并查看是否有掉帧或渲染性能问题。
- 使用 Android Studio 的 Frame Rendering Profiler 可以帮助你识别哪些帧超过了 16ms 的时间限制。
- Perfetto 能详细展示 VSYNC 和帧的绘制时间,帮助你找出导致掉帧的原因。
总结
使用 Choreographer
进行帧率优化的核心思想是将 UI 更新同步到系统的屏幕刷新信号(VSYNC)上,从而避免无效的绘制和过度渲染,提升性能。关键优化步骤包括:
- 使用
Choreographer
在doFrame()
回调中执行 UI 更新。 - 避免在主线程执行耗时任务,将其移到后台线程。
- 优化布局和绘制逻辑,减少不必要的嵌套和重绘。
- 使用
postOnAnimation()
来确保动画与帧率同步。
通过这些优化措施,可以大幅提升应用的流畅度,减少掉帧情况。
相关文章:

如何使用 Choreographer 进行帧率优化
Choreographer 是 Android 提供的一个工具类,专门用来协调 UI 帧的渲染。你可以通过 Choreographer 来精确控制帧的绘制时机,以优化帧率,确保应用的流畅度。以下是如何使用 Choreographer 进行帧率优化的详细步骤: 1. 理解 Chore…...

稳定驱动之选SiLM5350系列SiLM5350MDBCA-DG单通道隔离栅极驱动器(带内部钳位):工业自动化的可靠伙伴
SiLM5350系列SiLM5350MDBCA-DG是具体有10A峰值输出电流能力,单通道隔离式栅极驱动器。SiLM5350MDBCA-DG可提供内部钳位功能。驱动电源电压为4V至30V。3V至18V的宽输入VDDI范围使驱动器适合与模拟和数字控制器接口。所有电源电压引脚都有欠压锁定 (UVLO) 保护。 SiLM…...

鸿蒙OpenHarmony【轻量系统芯片移植】内核移植
移植芯片架构 芯片架构的移植是内核移植的基础,在OpenHarmony中芯片架构移植是可选过程,如果当前OpenHarmony已经支持对应芯片架构则不需要移植操作,在“liteos_m/arch”目录下可看到当前已经支持的架构,如表1: 表1 …...

多字节字符和宽字符
小时候,买东西的单位是一角、二角和五角,现在的单位是一元、五元和十元。人类社会的发展和计算机发展本质没啥两样,形态不同而已。 编码格式的历史 尽管早期只用ASCII码就可以表达所有字符,但计算机日益推广让其他国家不同语言的…...

C++缺省参数
个人主页:Jason_from_China-CSDN博客 所属栏目:C系统性学习_Jason_from_China的博客-CSDN博客 缺省参数的概念 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则…...

深度学习中的常用线性代数知识汇总——第一篇:基础概念、秩、奇异值
文章目录 0. 前言1. 基础概念2. 矩阵的秩2.1 秩的定义2.2 秩的计算方法2.3 秩在深度学习中的应用 3. 矩阵的奇异值3.1 奇异值分解(SVD)3.2 奇异值的定义3.3 奇异值的性质3.4 奇异值的意义3.5 实例说明3.6 奇异值在深度学习中的应用 0. 前言 按照国际惯例…...

MATLAB | R2024b更新了哪些好玩的东西?
Hey, 又到了一年两度的MATLAB更新时刻,MATLAB R2024b正式版发布啦!,直接来看看有哪些我认为比较有意思的更新吧! 1 小提琴图 天塌了,我这两天才写了个半小提琴图咋画,MATLAB 官方就出了小提琴图绘制方法。 小提琴图…...

嵌入式硬件基础知识
嵌入式硬件基础知识涵盖了嵌入式系统中的硬件组成及其工作原理,涉及处理器、存储器、外设接口、电源管理等多个方面。这些硬件共同构成了一个完整的嵌入式系统,用于执行特定任务。下面我们来详细介绍嵌入式硬件的基础知识。 1. 嵌入式系统的组成 嵌入式…...

keepalived和lvs高可用集群
keepavlied和lvs高可用集群搭建 主备模式: 关闭防火墙和selinux systemctl stop firewalld setenforce 0部署master负载调度服务器 zyj86 安装ipvsadm keepalived yum install -y keepalived ipvsadm修改主节点配置 vim /etc/keepalived/keepalived.conf! Conf…...

在VMware部署银河麒麟系统
虚拟机镜像安装文件从下面下载: 银河麒麟桌面操作系统V10SP1 2403 下载地址_银河麒麟v10镜像iso下载-CSDN博客 虚拟机安装要求硬盘大小至少40G,我悬着60G 选择桥接网络安装后上不了网并且和本机也互相ping不通,因此选择Nat方式,然后重启,就可以上网 下面开始安装,第一个…...
git删除本地分支报错:error: the branch ‘xxx‘ is not fully merged
git删除本地分支报错:error: the branch xxx is not fully merged error: the branch xxx is not fully merged 直接: git branch -D xxx 就可以。 如果删除远程分支: git push origin --delete origin/xxx git强制删除本地分支 git branc…...

Tensorflow 兼容性测试-opencloudos
介绍 Tensorflow 兼容性测试: 测试 Tensorflow 各个版本在 OpenCloudOS Stream 的安装支持 操作系统 [rootlab101 ~]# cat /etc/os-release NAME"OpenCloudOS Stream" VERSION"23" ID"opencloudos" ID_LIKE"opencloudos" VERSION_I…...

Windows主机上安装CUPS服务端共享USB打印机实践心得
背景 平时主力机器是Windows,不想额外开一个Linux服务器来共享打印机。由于主力机平时也不关机,尝试在Windows上安装CUPS服务。 结论 先说结论,结论是可行,但是麻烦且不稳定,虚拟机方案少折腾,但是资源消耗…...

socket通讯原理及例程(详解)
里面有疑问或者不正确的地方可以给我留言。 对TCP/IP、UDP、Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵。那么我想问: 什么是TCP/IP、UDP?Socket在哪里呢?Socket是什么呢࿱…...

vue3使用provide和inject传递异步请求数据子组件接收不到
前言 一般接口返回的格式是数组或对象,使用reactive定义共享变量 父组件传递 const data reactive([])// 使用settimout模拟接口返回 setTimeout(() > {// 将接口返回的数据赋值给变量Object.assign(data, [{ id: 10000 }]) }, 3000);provide(shareData, dat…...

对称矩阵的压缩存储
1.给自己出题:自己动手创造,画一个5行5列的对称矩阵 2.画图:按“行优先”压缩存储上述矩阵,画出一维数组的样子 3.简答:写出元素 i,j 与 数组下标之间的对应关系 4.画图:按“列优先”压缩存储上述矩阵&a…...

高阶数据结构之哈希表基础讲解与模拟实现
程序猿的读书历程:x语言入门—>x语言应用实践—>x语言高阶编程—>x语言的科学与艺术—>编程之美—>编程之道—>编程之禅—>颈椎病康复指南。 前言: 哈希表(Hash Table)是一种高效的键值对存储数据结构&…...

基于STM32设计的智能货架(华为云IOT)(225)
文章目录 一、前言1.1 项目介绍【1】项目背景【2】项目支持的功能【3】项目硬件模块组成【4】ESP8266工作模式配置【5】Android手机APP开发思路【6】项目模块划分1.2 项目开发背景【1】选题来源与背景【2】国内外研究现状【3】课题研究的目的和内容【4】参考文献【5】研究内容【…...

JDBC API详解一
DriverManager 驱动管理类,作用:1,注册驱动;2,获取数据库连接 1,注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); 查看Driver类源码 static{try{DriverManager.registerDriver(newDrive…...

工厂安灯系统在设备管理中的重要性
在现代制造业中,设备管理是确保生产效率和产品质量的关键环节。随着工业4.0的推进,越来越多的企业开始采用智能化的设备管理系统,其中安灯系统作为一种有效的管理工具,逐渐受到重视。安灯系统最初源于日本的丰田生产方式ÿ…...

【LabVIEW学习篇 - 23】:简单状态机
文章目录 简单状态机状态机的创建和了解状态机实现红绿灯 简单状态机 一个优秀的应用程序离不开好的程序框架,不仅要很好满足用户的功能需求,还要考虑到系统的稳定性、实时性、可扩展性、可维护性,执行效率等方面。借用一些成熟的设计框架&a…...

【CSS】 Grid布局:现代网页设计的基石
引言 最近接到一个网页布局比较复杂的页面,看了半天还是决定用grid布局来写,记录一下 布局是构建用户界面的关键部分。CSS Grid布局提供了一种简单而强大的方式来创建复杂的网格布局,它让设计师和开发者能够更直观、更灵活地控制网页的结构。…...

jQuery UI API 文档
关于《jQuery UI API 文档》,我找到了一些有用的信息。jQuery UI 是建立在 jQuery JavaScript 库上的一组用户界面交互、特效、小部件及主题。如果您是 jQuery 新手,建议您先查看 jQuery 教程。目前,我找到的资料主要是关于 jQuery UI 1.10 版…...

盘点2024年大家都在用的录屏工具
现在录屏工具的使用范围越来越广了。我的深切体验是有很多人愿意为知识付费了,但是到线下培训的话很多人时间不一定能协调的来,这就导致涌现了不少的录屏课程。这次我们来探讨下要怎么录屏才能呈现更好的效果。 1.福昕录屏大师 链接达达:ww…...

【大数据】探索怎么从一段话中解析关键信息(寄件人相关信息)
本文由ChatGPT生成,主要用于学习,大家有疑问请及时提出。 使用NLP实现文本信息解析功能:以提取姓名、地址和电话号码为例 在这个博客中,我们将通过自然语言处理(NLP)技术来实现一个简单的文本信息解析功能…...

初学者指南:MyBatis 入门教程
主要介绍了Mybatis的基本使用、JDBC、数据库连接池、lombok注解! 文章目录 前言 什么是Mybatis? 快速入门 使用Mybatis查询所有的用户信息 配置SQL提示 JDBC介绍 Mybatis 数据库连接池 lombok 总结 前言 主要介绍了Mybatis的基本使用、JDBC、数据库连接…...

reader-lm:小模型 html转markdown
参考: https://huggingface.co/jinaai/reader-lm-0.5b 在线demo: https://colab.research.google.com/drive/1wXWyj5hOxEHY6WeHbOwEzYAC0WB1I5uA#scrollTo0mG9ISzHOuKK 输入网址:https://www.galaxy-geely.com/E5 结果: 代码…...

进击J6:ResNeXt-50实战
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 一、实验目的: 阅读ResNeXt论文,了解作者的构建思路对比之前介绍的ResNet50V2、DenseNet算法使用ResNeXt-50算法完成猴痘病识别 二、实…...

新代机床采集数据
新代集團1995年成立於台灣新竹,事業版圖遍布全球,以台灣為中心向外發展,據點橫跨歐洲、美洲、亞洲三大洲。新代長期深耕於機床控制器的軟體及硬體技術研發,專注於運動控制領域,目前已成為亞太市場中深具影響力的控制器領導品牌之一。主營產品包括:機床數控系統、伺服驅動…...

景联文科技:专业数据标注公司,推动AI技术革新
数据标注作为AI技术发展的重要支撑,对于训练高质量的机器学习模型以及推动应用领域的创新具有不可替代的作用。 景联文科技作为专业的数据标注公司,致力于提供专业的数据标注服务,帮助客户解决AI链条中的数据处理难题,共同推动人工…...