当前位置: 首页 > article >正文

Android帧抢占协议技术剖析:触摸事件与UI绘制的智能调度优化方案

简介

在移动应用开发中,触摸事件响应与UI绘制的同步竞争是导致卡顿和掉帧的主要原因之一。腾讯工程师提出的优先级策略通过紧急事件抢占、增量渲染机制和时间片补偿技术,有效解决了这一竞争问题。本文将深入分析这些技术原理,并提供完整的代码实现,帮助开发者构建更流畅的用户体验。

一、技术背景与问题分析

1.1 Android帧渲染机制概述

Android系统采用垂直同步(VSync)机制确保屏幕刷新与UI渲染同步。在90Hz刷新率的华为Mate40 Pro上,每帧渲染时间间隔为约11ms,对渲染性能要求极高。系统通过SurfaceFlinger管理多个应用层的Surface,并将它们合成到屏幕上。每个应用的渲染流程包括测量(Measure)、布局(Layout)和绘制(Draw)三个阶段,通常在UI线程中执行。

Choreographer作为Android的"帧调度员",负责协调VSync信号与UI渲染任务。当VSync信号到达时,Choreographer会依次触发输入事件处理、动画更新和视图遍历等回调,确保UI更新在VSync周期内完成。

1.2 触摸事件与UI绘制的竞争问题

触摸事件处理与UI绘制在同一个VSync周期内的竞争可能导致严重卡顿。具体表现为:

  • 当用户快速滑动或连续点击时,大量触摸事件需要处理
  • 同时,UI需要重新布局和绘制
  • 如果主线程任务过多,导致在VSync周期内无法完成所有操作
  • 最终出现掉帧(Jank)现象,用户体验下降

华为Mate40 Pro在优化前帧抖动率高达18%,这表明其UI渲染与触摸事件处理之间存在严重的竞争问题。通过腾讯的优先级策略,这一问题得到了显著改善,帧抖动率降至3.2%。

1.3 优化策略的核心思想

腾讯的优先级策略包含三个核心组成部分:

  1. 紧急事件抢占:当存在未处理的ACTION_DOWN触摸事件时,延迟当前帧的UI绘制,确保用户交互得到及时响应
  2. 增量渲染机制:将UI绘制拆分为Background/Foreground阶段,允许在帧中期插入事件处理,减少单帧负载
  3. 时间片补偿:通过Choreographer.postFrameCallbackDelayed动态调整下一帧截止时间,避免连续掉帧

这些策略协同工作,确保在高负载场景下,触摸事件能够得到优先处理,同时UI渲染也能在合理时间内完成,从而显著提升用户体验。

二、触摸事件与UI绘制的竞争问题

2.1 输入事件与UI渲染的优先级矛盾

Android系统中,输入事件和UI渲染共享同一主线程资源。当用户触摸屏幕时,系统会生成MotionEvent对象并加入输入队列。在Choreographer的doFrame回调中,系统按固定顺序处理这些任务:

void doFrame(long frameTimeNanos) {// 处理输入事件doCallbacks(CALLBACK Input, frameTimeNanos);// 处理动画doCallbacks(CALLBACK ANIMATION, frameTimeNanos);// 处理视图遍历(测量、布局、绘制)doCallbacks(CALLBACK TRAVERSAL, frameTimeNanos);// 提交渲染数据doCallbacks(CALLBACK COMMIT, frameTimeNanos);
}

在高负载场景下,如果UI渲染阶段耗时过长,会导致下一VSync周期内无法处理新的输入事件。例如,在华为Mate40 Pro上,90Hz刷新率意味着每帧仅有约11ms的处理时间。如果UI渲染耗时超过11ms,系统会错过VSync信号,导致掉帧和输入延迟。

2.2 帧抖动率高的原因分析

华为Mate40 Pro优化前帧抖动率高达18%,主要原因包括:

  1. 单缓冲区渲染:在双缓冲机制下,当GPU仍在处理B帧时,CPU无法开始C帧的绘制,导致资源闲置
  2. 输入事件处理延迟:UI渲染阶段会阻塞后续输入事件的处理
  3. 动画与UI绘制耦合:动画计算和UI绘制共享同一VSync周期,容易互相影响
  4. 未优化的脏区域处理:系统默认重绘整个视图,即使只有小部分区域发生变化

这些因素共同导致在触摸事件频繁发生的场景下,UI渲染无法及时完成,造成帧抖动和卡顿现象。

三、腾讯优先级策略的实现原理

3.1 紧急事件抢占机制

紧急事件抢占是腾讯策略的核心,确保用户交互得到及时响应。当检测到未处理的ACTION_DOWN事件时,系统会延迟当前帧的UI绘制,优先处理触摸事件。

实现原理如下:

// 自定义Choreographer子类
public class CustomChoreographer extends Choreographer {private boolean hasPendingActionDown = false;@Overridepublic void doFrame(long frameTimeNanos) {// 检测是否有未处理的ACTION_DOWN事件if (hasPendingActionDown) {// 优先处理输入事件doCallbacks(CALLBACK Input, frameTimeNanos);// 延迟UI渲染postFrameCallbackDelayed(new FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {// 处理UI渲染doCallbacks(CALLBACK TRAVERSAL, frameTimeNanos);doCallbacks(CALLBACK COMMIT, frameTimeNanos);}}, 0);hasPendingActionDown = false;return;}// 正常处理流程doCallbacks(CALLBACK Input, frameTimeNanos);doCallbacks(CALLBACK ANIMATION, frameTimeNanos);doCallbacks(CALLBACK TRAVERSAL, frameTimeNanos);doCallbacks(CALLBACK COMMIT, frameTimeNanos);}// 在InputDispatcher中设置标志public void setPendingActionDown(boolean hasPending) {hasPendingActionDown = hasPending;}
}

通过这种机制,系统可以确保在用户按下屏幕的瞬间,触摸事件得到及时处理,避免因UI渲染阻塞导致的输入延迟

3.2 增量渲染机制实现

增量渲染机制将UI绘制拆分为Background和Foreground阶段,允许在帧中期插入事件处理,减少单帧负载。

实现原理如下:

// 自定义ViewGroup实现增量渲染
public class IncrementalLayout extends ViewGroup {private boolean isBackgroundReady = false;private boolean is ForegroundReady = false;private Rect dirtyRegion = new Rect();public IncrementalLayout(Context context) {super(context);// 启用硬件加速setLayerType(LAYER_TYPE Software, null);}@Overrideprotected void onDraw(Canvas canvas) {if (!isBackgroundReady) {// 阶段1:绘制背景(固定内容)drawBackground canvas);isBackgroundReady = true;}if (!is ForegroundReady) {// 阶段2:绘制前景(变化内容)canvas.clipRect脏区域);drawForeground canvas);is ForegroundReady = true;} else {// 完整帧绘制drawBackground canvas);drawForeground canvas);}}// 在事件处理或动画回调中更新脏区域public void updateDirtyRegion(Rect region) {脏区域.union(region);invalidate脏区域);}// 重置渲染状态public void resetRenderState() {isBackgroundReady = false;is ForegroundReady = false;dirtyRegion.setEmpty();}
}

增量渲染通过将UI拆分为固定和变化部分,减少单帧绘制负载,提高渲染效率。在触摸事件处理过程中,系统仅重绘变化区域,而不是整个界面,从而减轻主线程负担。

3.3 时间片补偿技术

时间片补偿技术通过动态调整下一帧截止时间,避免连续掉帧。当检测到当前帧渲染超时后,系统会延长下一帧的截止时间,给渲染提供更多的缓冲时间。

实现原理如下:

// 帧时间监控与补偿
public class FrameCompensator implements FrameCallback {<

相关文章:

Android帧抢占协议技术剖析:触摸事件与UI绘制的智能调度优化方案

简介 在移动应用开发中,触摸事件响应与UI绘制的同步竞争是导致卡顿和掉帧的主要原因之一。腾讯工程师提出的优先级策略通过紧急事件抢占、增量渲染机制和时间片补偿技术,有效解决了这一竞争问题。本文将深入分析这些技术原理,并提供完整的代码实现,帮助开发者构建更流畅的…...

Maven 项目介绍

一、Maven 概述​ Maven 是一个基于 Java 的项目管理和构建自动化工具&#xff0c;由 Apache 软件基金会开发。它采用 “约定优于配置”&#xff08;Convention Over Configuration&#xff09;的原则&#xff0c;通过标准化的项目结构和配置&#xff0c;极大地简化了项目的构建…...

班迪录屏--解决视频剪辑时声音和画面不同步的问题

原文网址&#xff1a;班迪录屏--解决视频剪辑时声音和画面不同步的问题_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何用班迪录屏解决视频剪辑时声音和画面不同步的问题。 问题描述 我用班迪录屏录了视频&#xff0c;用剪映进行剪辑&#xff0c;结果发现在剪辑时声音和画面…...

Git上传项目到GitHub

Git上传项目到GitHub 下载Git客户端配置Git设置GitHub上传本地项目到Github 下载Git客户端 网址&#xff1a;Git Windows客户端。选择Standalone Installer(单独安装程序)&#xff0c;并点击64bit Git for Windows Setup(64位Git for Windows安装程序)进行下载。然后一路默认选…...

【工具】Quicker/VBA|PPT 在指定位置添加有颜色的参考线

文章目录 效果展示使用方式技术原理更多原理ActivePresentation.Guides 概述主要属性和方法使用示例添加水平参考线添加垂直参考线删除所有参考线获取参考线数量 注意事项 致谢 效果展示 先展示效果&#xff1a; Quicker 动作&#xff1a;VBA 添加参考线 - Quicker 动作 使用…...

第34节:迁移学习中的特征提取方法

迁移学习中的特征提取方法:原理、技术与应用 1. 迁移学习与特征提取概述 迁移学习(Transfer Learning)作为机器学习领域的重要范式 通过将源领域(source domain)学到的知识迁移到目标领域(target domain),有效解决了传统机器学习需要大量标注数据的瓶颈问题。 在迁…...

C语言中的文件I/O

C标准I/O库函数 1、C标准I/O库函数1.1、打开/写入/读取/关闭文件1.2、读取文件数据1.2.1、fgetc1.2.2、fgets1.2.3、fscanf1.3、标准输入/输出/错误2、系统调用2.1、常用的系统调用2.2、综合小demo3、文件描述符3.1、定义3.2、`文件描述符`关联的数据结构3.2.1、struct file3.2…...

(万字长文)Django数据库操作——ORM:数据交互显示前端网页

&#x1f31f; 如果这篇文章触动了你的心弦&#xff0c;请不要吝啬你的支持&#xff01; 亲爱的读者&#xff0c; 感谢你花时间阅读这篇分享。希望这里的每一个字都能为你带来启发或是让你会心一笑。如果你觉得这篇文章有价值&#xff0c;或者它解决了你一直以来的一个疑问&a…...

实验-使用递归计算阶乘-RISC-V(计算机组成原理)

目录 一、实验内容 二、实验步骤 三、实验效果 四、实验环境 五、实验小结和思考 一、实验内容 一个典型的计算阶乘的递归过程如下图所示&#xff1a; 在这个任务中&#xff0c;一份汇编代码的框架“task4-阶乘”你需要使用RISC-V或MIPS汇编程序以递归的形式解决这个问题。…...

ISO 26262-5 评估硬件架构度量值

两种硬件架构的度量&#xff0c; 用于评估相关项架构应对随机硬件失效的有效性。 应评估&#xff08;评估仅限于ASIL (B)、 C 和 D 的安全目标&#xff09; 1 应将按照附录 C 单点故障度量和潜伏故障度量的诊断覆盖率来评估 2 应结合残余故障和相关的潜伏故障来预估安全机制…...

JMeter 教程:响应断言

目录 JMeter 教程&#xff1a;响应断言的简单介绍【轻松上手】 ✅ 什么是响应断言&#xff1f; &#x1f4cc; 使用场景示例 &#x1f6e0;️ 添加响应断言步骤 1. 选中 HTTP 请求 → 右键 → Add → Assertions → Response Assertion 2. 设置断言内容&#xff1a; ✅ …...

【Qt开发】显示类控件——QLCDNumber

目录 1&#xff0c;QLCDNumber的说明 2&#xff0c;QLCDNumber的运用 1&#xff0c;QLCDNumber的说明 QLCDNumer 是一个专门用来显示数字的控件。它类似于 "老式计算器" 的效果。它的核心属性如下&#xff1a; 2&#xff0c;QLCDNumber的运用 定时器 运用QLCDNumb…...

深入剖析 5G 核心网中的 PLMN

一、引言 在 5G 技术迅猛发展的当下,5G 核心网作为整个通信系统的关键枢纽,支撑着海量数据传输、低延迟通信以及多样化业务应用。其中,公共陆地移动网络(Public Land Mobile Network,PLMN)扮演着极为重要的角色,它是 5G 核心网实现用户接入、网络管理以及业务提供的基础…...

音频AAC编码与RV1126的AENC模块的讲解

一.音频编码的原理 AAC编码的基本概念 AAC&#xff08;Advanced Audio Coding&#xff09;是一种高级音频编码格式&#xff0c;旨在提供比MP3更高的音质和更低的比特率。AAC是MPEG-2和MPEG-4标准的一部分&#xff0c;广泛应用于音乐、视频流媒体和广播等领域 音频为什么要进…...

vue页面目录菜单有些属性是根据缓存读取的。如果缓存更新了。希望这个菜单也跟着更新。

父组件中有两个子组件。如果在B组件数据更新之后。A组件也跟着一起改变呢&#xff1f;如图如果我右边基本信息里面勾选了高血压&#xff0c;左侧菜单里面也要立刻出现一个高血压随访菜单&#xff0c;如果我取消勾选了左侧菜单就去掉。 左侧菜单的显示和隐藏的数据实际上是放在…...

Android开发-Application

在Android应用开发中,Application类扮演着非常重要的角色。它作为整个应用程序的全局单例实例存在,在应用启动时最先被创建,并且在整个应用生命周期内持续存在。通过自定义Application类,开发者可以执行全局初始化操作、管理全局状态或数据等。本文将详细介绍Application的…...

在TIA 博途中下载程序时找不到对应的网卡怎么办?

1. 检查物理连接 确认网线已正确连接PLC和PC&#xff0c;接口指示灯正常。 尝试更换网线或交换机端口&#xff0c;排除硬件故障。 2. 确认网卡驱动已安装 设备管理器检查&#xff1a; 右键点击“此电脑” → “管理” → “设备管理器”。 展开“网络适配器”&#xff0c;确…...

《量子计算实战》PDF下载

内容简介 在加密、科学建模、制造物流、金融建模和人工智能等领域&#xff0c;量子计算可以极大提升解决问题的效率。量子系统正变得越来越强大&#xff0c;逐渐可用于生产环境。本书介绍了量子计算的思路与应用&#xff0c;在简要说明与量子相关的科学原理之后&#xff0c;指…...

Linux入门(部分基础相关知识+常用命令+权限)

目录 1.基础背景了解 2、基本操作系统、linux相关知识 1.操作系统是一款用来管理软硬件资源的软件。 2.对于一个文件来说&#xff0c;是由文件内容文件属性构成的。空文件&#xff08;内容为空&#xff09;也占磁盘空间。 3.linux下的目录结构 4.linux下的删除 5.环境 6…...

海拔案例分享-实践活动报名测评小程序

大家好&#xff0c;今天湖南海拔科技想和大家分享一款实践活动报名测评小程序&#xff0c;客户是长沙一家专注青少年科创教育的机构&#xff0c;这家机构平时要组织各种科创比赛、培训课程&#xff0c;随着学员增多&#xff0c;管理上的问题日益凸显&#xff1a;每次组织活动&a…...

JavaWeb面试题 (一)

1. 常见的软件系统结构 1. C/S C/S结构即客户端/服务器&#xff08;Client/Server&#xff09;&#xff0c;例如QQ&#xff1b; 缺点&#xff1a;软件更新时需要同时更新客户端和服务器端两端&#xff0c;比较麻烦&#xff1b; 优点&#xff1a;安全性比较好 2. B/S B/S结…...

解决Vue项目依赖错误:使用electron-vite重建

文章目录 开端解决方案&#xff1a;使用 electron-vite Vue 重建项目1. 环境准备2. 创建新项目3. 安装依赖并启动项目 开端 在开发过程中&#xff0c;我遇到了一个令人头疼的错误提示&#xff1a; 0:0 error Parsing error: Cannot find module vue/cli-plugin-babel/preset…...

vue3样式穿透用法

在Vue3中&#xff0c;样式穿透可通过以下方式实现&#xff1a; 1. 基础用法 使用::v-deep伪类实现样式穿透&#xff08;兼容Vue2语法&#xff09;&#xff1a; .parent ::v-deep .child-component {color: red; }2. 推荐方式 使用:deep()伪函数&#xff08;Vue3推荐写法&am…...

Puppeteer 浏览器自动化操作工具

pyppeteer 是 Python 版本的 Puppeteer&#xff0c;而 Puppeteer 是由 Google 开发的一个 Node.js 库&#xff0c;用于控制 Chrome 或 Chromium 浏览器。pyppeteer 允许你通过 Python 代码自动化操作浏览器&#xff0c;实现网页爬取、自动化测试、生成截图或 PDF 等功能。 核心…...

5G 网络寻呼的信令及 IE 信息分析

一、寻呼信令的触发背景 在 5G 网络中,当网络侧有下行数据要发送给处于空闲态(RRC_IDLE)或非激活态(RRC_INACTIVE)的用户设备(UE)时,就会触发寻呼流程。这是因为在这些状态下,UE 与网络之间没有建立持续的无线资源控制(RRC)连接,网络需要通过寻呼机制来通知 UE 有…...

信奥赛CSP动态规划入门-最小硬币问题

针对**“最小硬币问题”**的详细分步解析与程序实现&#xff0c;通过将大问题分解为小问题的方式讲解动态规划的应用&#xff1a; 一、问题拆解步骤 1. 明确问题定义 大问题&#xff1a;用面值1元和5元的硬币凑出N元&#xff0c;最少需要多少枚硬币&#xff1f; 小问题&#…...

cmd里可以使用npm,vscode里使用npm 报错

cmd里可以使用npm,vscode里使用npm 报错 报错提示原因解决方法 报错提示 npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1&#xff0c;因为在此系 统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/ fwlink/?LinkID135170 中的 about_Executi…...

JAVA开发工具延长方案

亲测稳定的延长方案与避坑指南 真的搞不懂了&#xff0c;说点专业的术语竟然成了 QINQUAN。那就直接点&#xff0c;把这个方案带给需要的开发者。 延长工具直通车 保姆级教程 延长方案https://mp.weixin.qq.com/s/uajM2Y9Vz6TnolzcLur_bw还是让大家看看&#xff0c;发什么会被…...

CSS 浮动(Float)及其应用

1. 什么是浮动&#xff08;Float&#xff09;&#xff1f; 浮动元素会脱离正常的文档流&#xff08;Document Flow&#xff09;&#xff0c;并向左或向右移动&#xff0c;直到碰到父元素的边缘或另一个浮动元素。 基本语法 .float-left {float: left; }.float-right {float:…...

CC53.【C++ Cont】一维前缀和

目录 1.定义 2.作用 3.例题:【模板】一维前缀和 分析 方法1:暴力解法 方法2:前缀和(简单的动态规划) 第一步:预处理 4.练习:P1115 最大子段和 分析 方法1:段长从1枚举到n 方法2:改进方法1 代码 提交结果 1.定义 快速求出数组中某一段的区间和,时间复杂度为(速度极…...