Android 刷新与显示

news2024/9/22 17:33:31

目录

屏幕显示原理:

显示刷新的过程

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这个方法,开始进行遍历等一系列操作。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第三章 CUDA编译器环境配置篇

cuda教程目录 第一章 指针篇 第二章 CUDA原理篇 第三章 CUDA编译器环境配置篇 第四章 kernel函数基础篇 第五章 kernel索引(index)篇 第六章 kenel矩阵计算实战篇 第七章 kenel实战强化篇 第八章 CUDA内存应用与性能优化篇 第九章 CUDA原子(atomic)实战篇 第十章 CUDA流(strea…

Fatal error, can‘t open config file ‘/myredis/redis.conf‘: No such file or directory

在学习Redis到主从复制部分,进行相关练习,基本过程如下 1.首先将redis.conf文件cp到自建myredis文件夹中,并配置不同端口号的redis.conf redisXXXX.confd的配置内容如下 : include /myredis/redis.conf pidfile /var/run/redis_…

压力测试与测试工具jmeter的介绍

目录 一、性能指标 二、jmeter (一)JMeter 安装 (二)JMeter 压测示例 1、添加线程组 2、添加 HTTP 请求 3、添加监听器 4、启动压测&查看分析结果 (三)JMeter Address Already in use 错误解决 压力测…

Flutter运行app时向logcat输出当前打开的界面路径且点击可跳转

当一个项目大了目录文件多了,我们往往会为了找到一个文件花费大量的时间和精力,为了快捷方便的调试我们的项目,我们往往需要在打开app运行的时候需要知道当前打开的界面的文件在哪儿,我们这个代码就能快捷的知道我们app正在打开的…

《HeadFirst设计模式(第二版)》第五章代码——单例模式

代码文件目录: 初始版本: package Chapter5_SingletonPattern.origin;/*** Author 竹心* Date 2023/8/5**/public class Singleton {private static Singleton uniqueInstance;private Singleton(){}public static Singleton getInstance(){if(uniqueIn…

2023牛客暑期多校训练营6-A Tree

2023牛客暑期多校训练营6-A Tree https://ac.nowcoder.com/acm/contest/57360/A 文章目录 2023牛客暑期多校训练营6-A Tree题意解题思路代码 题意 解题思路 最大价值和这个数据范围,一眼 d p dp dp。 直接在树上并不好处理,问题是如何有效转化、处理…

黑马程序员SpringMVC练手项目

目录 1、需求 2、项目准备 pom.xml SQL jdbc.properties log4j.properties applicationContext.xml spring-mvc.xml web.xml 3、工作流程 4、难点 项目已经上传到gitee:https://gitee.com/xzl-it/my-projects 1、需求 SpringMVC项目练习:数…

每日一题——反转单链表

反转单链表 题目链接 下面主要介绍两种方法: 方法一: 利用三个指针变量进行反转 具体过程如图所示: 注意:循环的结束的条件为cur NULL而不是next NULL 实现代码: struct ListNode* reverseList(struct ListNode* …

STL容器适配器 -- stack和queue(使用+实现)(C++)

stack和queue stackstack的介绍stack的使用stack的实现 queuequeue的介绍queue的使用queue的实现 deque简单介绍deque(双端队列)双开口连续打引号的原因 deque底层结构deque的迭代器封装结构(复杂)deque的优缺点 栈和队列数据结构…

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 .然后…

JVM入门到精通

一、JVM概念 1.1、什么是JVM Java Virtual Machine:Java虚拟机,用来保证Java语言跨平台 Java虚拟机可以看做是一台抽象的计算机,如同真实的计算机那样,它有自己的指令集以及各种运行时内存区域 Java虚拟机与Java语言并没有必然…

Maven-搭建私有仓库

使用NEXUS REPOSITORY MANAGER 3在Windows上搭建私有仓库。 NEXUS REPOSITORY MANAGER 3 是一个仓库管理系统。 下载NEXUS3 官网上是无法下载的,所以网上搜nexus-3.18.1-01-win64就能搜到,下载即可。 安装NEXUS3 下载nexus-3.18.0-01-win64.zip至相应目录下(路径不要有中文)。 …

[Realtek sdk-3.4.14b]RTL8197FH-VG+RTL8812F WiFi开启访客网络之后无法扫描到SSID问题分析及解决方案

问题描述 realtek sdk-3.4.14b 开启访客网络之后,发现无法扫描到SSID,可以看到接口已经up,但是设备无法搜到WiFi热点 问题分析 查看网口状态 ifconfig查看wlan0-va0接口TX/RX的数据包都是0,表示没有发送或者接收到数据包,正常wifi启动之后,都会有Beacon包发出,也会接…

【Redis】——RDB快照

Redis 是内存数据库,但是它为数据的持久化提供了两个技术,一个是AOF日志,另一个是RDB快照: AOF 文件的内容是操作命令;RDB 文件的内容是二进制数据。 RDB 快照就是记录某一个瞬间的内存数据,记录的是实际…

Vue中,$forceUpdate()的使用

在Vue官方文档中指出,$forceUpdate具有强制刷新的作用。 那在vue框架中,如果data中有一个变量:age,修改他,页面会自动更新。 但如果data中的变量为数组或对象,我们直接去给某个对象或数组添加属性,页面是识…

JMeter 4.x 简单使用

文章目录 前言JMeter 4.x 简单使用1. 启动2. 设置成中文3. 接口测试3.1. 设置线程组3.2. HTTP信息请求头管理器3.3. 添加HTTP请求默认值3.4. 添加HTTP cookie 管理3.5. 添加http请求3.5.1. 添加断言 3.6. 添加监听器-查看结果树3.7. 添加监听器-聚合报告 4. 测试 前言 如果您觉…

TBB库中实现协程(coroutine)的源码说明

源码请见: https://github.com/oneapi-src/oneTBB/blob/master/src/tbb/co_context.h 在windows系统,TBB(也就是intel 的 oneTBB库),通过windwos fiber(纤程)来实现协程(coroutine)。 创建一个协程,代码很简洁: inline void create_coroutine(corouti…

docker【安装、存储、镜像、仓库、网络、监控】

docker-0110.0.0.51docker-0210.0.0.52docker-0310.0.0.53 【1】docker安装 docker-01 [rootdocker-01 ~]# vim /etc/yum.conf [main] cachedir/var/cache/yum/$basearch/$releasever keepcache1 debuglevel2 logfile/var/log/yum.log exactarch1 obsoletes1 gpgcheck1 plugin…

安防监控视频融合EasyCVR平台接入RTSP流后设备显示离线是什么原因?

安防监控视频EasyCVR视频汇聚融合平台基于云边端智能协同架构,具有强大的数据接入、处理及分发能力,平台支持海量视频汇聚管理、全网分发、按需调阅、鉴权播放、智能分析等视频能力与服务。平台开放度高、兼容性强、可支持灵活拓展与第三方集成&#xff…