Android 刷新与显示

目录

屏幕显示原理:

显示刷新的过程

VSYNC机制具体实现

小结:


屏幕显示原理:

过程描述:

应用向系统服务申请buffer

系统服务返回一个buffer给应用

应用开始绘制,绘制完成就提交buffer,系统服务把buffer数据提供给屏幕

这样,屏幕就能显示应用绘制的显示数据了

如果只有一个缓存,那么屏幕在还没有读完缓存数据的时候,系统服务又在写缓存数据,那么屏幕读取的这一帧数据其实就包含了两帧的数据,显示出来的可能一半是第一帧,一半是第二帧数据了。解决这个问题可以采用双缓冲区的方式。

这个操作过程大概是这样的,缓存1用于系统服务写数据,缓存2就用来给屏幕读取,

当屏幕需要读完缓存1的数据后需要读取下一帧数据,那么就把指针切换到缓存2来读取即可,同理系统服务就往缓存1来写数据,如此交替,就使得缓存的读写独立开来互不影响了。

显示刷新的过程

安卓定义的是60Hz的刷新率,就是每16ms屏幕的数据会刷新一次

那么我们分析一下显示刷新的过程:

应用进行绘制,然后由系统服务进行渲染并输出屏幕显示数据到缓存,屏幕读取缓存数据进行刷新显示。

第1帧:绘制渲染正常,所以屏幕能够正常显示第1帧数据

第2帧:没能在16ms内完成,因此就无法提供这一帧屏幕数据给缓存,所以屏幕也只能继续读取旧的数据,也就是第1帧数据。我们从视图描述看,第2帧的性能优化的不错,远远小于16ms,但是这一帧之所以会没能在16ms内完成绘制渲染提供缓存出来,是因为这一帧绘制的比较晚,导致这一帧还没有绘制完成就到了16ms了,这就是掉帧。如果这样的情况多了,就会让用户明显感受到卡顿。

该怎么解决这个问题呢?答案是:Vsync信号

如果有个Vsync信号,来通知应用绘制,那么这样就能实现每一帧都比较完美地在16ms内完成绘制渲染,提供显示数据了。

这就是Vsync给应用和服务进行绘制渲染提供同步信号的基本原理了

VSYNC机制具体实现

上面讲解vsync原理的时候为了简单起见,把绘制和渲染结合一起了,实际上绘制和渲染是由不同的进程,不同的硬件来处理的。在Android系统中,绘制是由应用app来做的,对应CPU的操作,合成与渲染是由SurfaceFlinger完成,对应的是GPU。现在的问题是一个Vsync信号只有1个,怎么来同时对两个进程提供同步信号呢?Android系统中的做法是一分为二,就是把信号分为vsync-app和vsync-sf,同时也引入一个指挥家Choreographer,进行操作指导。

我们先从请求绘制开始:

/frameworks/base/core/java/android/view/ViewRootImpl.java

1)往消息队列插入SyncBarrier:这是一个屏障,把消息插入队列里就不可以处理普通消息,等到这个屏障撤除了才可以进行普通消息的处理。对异步消息是不影响的。

一次Vsync周期只能触发一次requestLayout,只会绘制一次

2)往mChoreographer插入Callback,mTraversalRunnable就是一个异步消息,需要紧急处理

Choreographer是与ViewRootImpl一起创建的

sThreadInstance是一个ThreadLocal,在不同的线程去getInstance可以得到不同的Choreographer的对象

Callback是怎么加到Choreographer里面呢?

 /frameworks/base/core/java/android/view/Choreographer.java

final long now = SystemClock.uptimeMillis();获取下一vsync的时间戳

dueTime就是从这个时间后延迟多久

mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);

一个CallbackQueues队列,不同的callbackType有不同的队列,包含有3个参数

如果dueTime小于现在的时间戳那么就是说下一帧就要被处理的。直接调scheduleFrameLocked处理,如果是大于下一次vsync的时间,则需要通过handler发送一个异步消息,等待处理。

代码可以看到,跑在所在looper的线程的时候就会立刻调度vsync,否则就尽快post一个消息去UI线程。所以就使用了Handler发送一个异步消息,

当vsync来的时候就会调用这个FrameDisplayEventReceiver,里面的timestampNanos就是这个vsync信号的时间戳,

绘制的时候jitterNanos如果大于一个时间周期,并且超过了SKIPPED_FRAME_WARNING_LIMIT的警告值就会给出一个警告,应用主线程耗时操作。

上面是属于计算时间的阶段,那么下一阶段就是一系列的回调阶段,包括:

从callbackqueue里面取出带有时间戳的callback进行处理

小结:

应用层的View调用了requestLayout要重绘,其实就是new了一个Choreographer丢到消息队列里面,然后Choreographer没有马上去处理消息,而是先是调用requestNextVsync函数向SurfaceFlinger请求下一个的vsync信号。然后SurfaceFlinger就会在下一个vsync信号来的时候通过postSyncEvent 向Choreographer发送一个通知,Choreographer接收到通知后就会去处理消息队列里面的消息,之前真正处理requestLayout的就是performTraversal这个方法,开始进行遍历等一系列操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/62520.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis实战(5)——Redis实现消息队列

消息队列,顾名思义,就是一个存放消息的队列。最简单的消息队列包含3个角色 生产者:将消息存入队列中队列:存放和管理消息消费者: 将消息从队列中取出来并做业务处理 R e d i s 提供了三种实现消息队列的方式&#x…

Linux性能学习(4.5):网络_TCP四次挥手内核参数优化

文章目录 1 四次挥手2 参数优化2.1 tcp_orphan_retries--->FIN报文重传次数2.2 tcp_max_orphans--->孤儿连接最大数量2.3 tcp_fin_timeout--->FINE_WAIT2状态等待时间2.4 tcp_max_tw_buckets2.5 tcp_tw_reuse--->复用未释放的端口 3 总结 参考资料: 1. …

星图按转化线索回传对接思路与示例

一、什么是星图?二、什么是线索转化?三、对接中的一些疑问?四、如何对接开发?五、星图侧如何联调测试? 一、什么是星图? 抖音星图是抖音电商蓝图下,为品牌方、MCN公司和明星/达人服务并收取分…

【DFS】17. 电话号码的字母组合

【DFS】17. 电话号码的字母组合 Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法…感兴趣就关注我bua! TOC 题目: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rikjhVFD-1691333891079)(C:\Us…

IAR开发环境的安装、配置和新建STM32工程模板

IAR到环境配置到新建工程模板-以STM32为例 一、 简单介绍一下IAR软件1. IAR的安装(1) 下载IAR集成开发环境安装文件(2) 安装 2. 软件注册授权 二、IAR上手使用(基于STM32标准库新建工程)1、下载标准库文件2、在IAR新建工程&#x…

华为云交付

文章目录 一、华为云-公有云架构华为公有云的主要服务1.华为云服务—计算类2.华为云服务——存储类3.华为云服务—网络类4.华为云服务—管理和监督类5.华为云数据库 二、待续 一、华为云-公有云架构 华为公有云的主要服务 ECS:弹性云服务器( Elastic Cl…

交互流程图设计软件都有哪些?

交互流程图是设计行业信息流、观点流或组件流的图形代表。但是市场上应该如何选择各种交互流程图软件呢?如何使用高质量的交互流程图软件来绘制高端氛围的高档流程图?今天,小边给您带来了十个超级实用的交互流程图软件,我希望能帮…

解决宝塔面板升级获取更新包失败,请稍后更新或联系宝塔运维

宝塔Linux面板执行升级命令后失败,提示“获取更新包失败,请稍后更新或联系宝塔运维”如何解决?新手站长分享宝塔面板升级失败的解决方法: 宝塔面板升级失败解决方法 1、使用root账户登录到你的云服务器上,宝塔Linux面…

亿欧智库:2023中国宠物行业新趋势洞察报告(附下载)

关于报告的所有内容,公众【营销人星球】获取下载查看 核心观点 户外赛道本质上迎合了全球共性需求的增长,从养宠意愿的转化到养宠生活的需求,多层次的需求推动行业发展新趋势 从需求端进行分析,可以将养宠意愿的转化分为三个层…

Python语法:... for ... in ... if ...

Python中,for...in...[if]...语句是一种简洁的构建List的方法,从for给定的List中选择出满足if条件的元素组成新的List,其中if是可以省略的。下面举几个简单的例子进行说明 [for in ]: ...for ....in..... 语句. 实例如下: (1) …

零知识证明技术概述

简述 隐私泄露问题给企业带来了巨大的损失,本文简述零知识证明技术并且给出对应的应用示例: 什么是零知识证明? 零知识证明又被称为零知识协议,利用数学知识在双方不需要直接传递信息本身的前提下来验证信息的正确性。这个思想…

LLM reasoners 入门实验 24点游戏

LLM reasoners Ber666/llm-reasoners 实验过程 实验样例24games,examples/tot_game24,在inference.py中配置使用代理和open ai的api key。 首先安装依赖 git clone https://github.com/Ber666/llm-reasoners cd llm-reasoners pip install -e .然后…

【JAVA】继承

作者主页:paper jie的博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《JAVASE语法系列》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精…

437. 路径总和 III

题目描述: 主要思路: 方法一:递归 从每个节点开始一次递归 class Solution { public:int ans0;void dfs(TreeNode* now,int targetSum, long sum){if(!now)return;sumnow->val;if(sumtargetSum)ans1;dfs(now->left,targetSum,sum);df…

[Docker实现测试部署CI/CD----构建成功后钉钉告警(7)]

目录 15、钉钉告警创建项目群,然后添加机器人添加机器人Jenkins 系统配置项目配置修改Jenkinsfile文件,添加钉钉提示信息测试 不修改Jenkinsfile文件,添加钉钉提示信息测试 15、钉钉告警 创建项目群,然后添加机器人 首先需要在钉…

Grafana制作图表-自定义Flink监控图表

简要 有时候我们在官网的Grafana下载的图表是这样的,如下图 #算子的处理时间,就是处理数据的延迟数据抓取,这个的说明看下下面的文章 metrics.latency.interval: 60 metrics.reporter.promgateway.class: org.apache.flink.metrics.prometh…

websocket服务端大报文发送连接自动断开分析

概述 当前springboot版本&#xff1a;2.7.4 使用依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>现象概述&#xff1a; 客户端和服务端已经有心跳…

《大型网站技术架构》第二篇 架构-高可用

高可用在公司中的重要性 对公司而言&#xff0c;可用性关系网站的生死存亡。对个人而言&#xff0c;可用性关系到自己的绩效升迁。 工程师对架构做了许多优化、对代码做了很多重构&#xff0c;对性能、扩展性、伸缩性做了很多改善&#xff0c;但别人未必能直观地感受到&#…

windows系统安装ElasticSearch7.9.3笔记

windows系统安装ElasticSearch7.9.3笔记 从es中文社区 或elastic官网下载安装包 ES中文社区-浏览器地址https://elasticsearch.cn/download/ 下载7.9.3版本的相关安装包 下载的安装包清单如下 开始配置使用带ik分词器和拼音分词器的ES7.9.3 分别解压这3个zip 拷贝ik分词器…

MATLAB(R2023a)添加工具箱TooLbox的方法-以GPOPS为例

一、找到工具箱存放位置 首先我们需要找到工具箱的存放位置&#xff0c;点击这个设置路径可以看到 我们的matlab工具箱的存放位置 C:\Program Files\MATLAB\R2023a\toolbox\matlab 从资源管理器中打开这个位置&#xff0c;可以看到里面各种工具箱 二、放入工具箱 解压我们…