Giter VIP home page Giter VIP logo

Comments (11)

FeatherHunter avatar FeatherHunter commented on May 22, 2024 39

界面刷新的本质流程

  1. 通过ViewRootImplscheduleTraversals()进行界面的三大流程。
  2. 调用到scheduleTraversals()时不会立即执行,而是将该操作保存到待执行队列中。并给底层的刷新信号注册监听。
  3. VSYNC信号到来时,会从待执行队列中取出对应的scheduleTraversals()操作,并将其加入到主线程消息队列中
  4. 主线程消息队列中取出并执行三大流程: onMeasure()-onLayout()-onDraw()

同步屏障的作用

  1. 同步屏障用于阻塞住所有的同步消息(底层VSYNC的回调onVsync方法提交的消息是异步消息)
  2. 用于保证界面刷新功能的performTraversals()的优先执行。

同步屏障的原理?

  1. 主线程的Looper会一直循环调用MessageQueuenext方法并且取出队列头部的Message执行,遇到同步屏障(一种特殊消息)后会去寻找异步消息执行。如果没有找到异步消息就会一直阻塞下去,除非将同步屏障取出,否则永远不会执行同步消息
  2. 界面刷新操作是异步消息,具有最高优先级
  3. 我们发送的消息是同步消息,再多耗时操作也不会影响UI的刷新操作

from android-daily-interview.

nealkafuly avatar nealkafuly commented on May 22, 2024 19

哦哦,原来可以根据系统做了什么,然后就可以避免一些搞耗时的动作,比如布局层数减少,这个题目的目的就在这里,会优化就完事啦,还搞这些,浪费时间。

from android-daily-interview.

979451341 avatar 979451341 commented on May 22, 2024 18

楼上讲了 应用层,我就说一下 系统层的,
首先屏幕是 大约16.6ms刷新一次(固定的),当界面需要改变时, CPU开始计算,将计算结果 赋予 GPU 的buffer缓存起来,等待刷新时间的到来,然后根据buffer的数据刷新界面
如果当前界面没有变化,CPU不用计算,也不会给GPU的buffer赋值啥的,这个buffer也就没变化,等到刷新时间的到来,会依旧根据buffer刷新屏幕

结论是:界面改不改变都会刷新界面,只是在于CPU是否计算这点区别

UI刷新卡顿,基本都在于卡在CPU计算这一环节,对于根据GPU 的buffer刷新这一环节,在系统里有很高的优先级,楼上就说了同步屏障就是保护这一优先级的一个手段

from android-daily-interview.

risechen avatar risechen commented on May 22, 2024 8

(1)简单概括:
Android应用程序把经过测量、布局、绘制后的surface缓存数据,通过SurfaceFlinger把数据渲染到屏幕上,通过Android的刷新机制来刷新数据。即应用层负责绘制,系统层负责渲染,通过进程间通信把应用层需要绘制的数据传递到系统层服务,系统层服务通过显示刷新机制把数据更新到屏幕
(2)应用层:相当于client,把计算好的图层数据通过共享内存shareclient传递给系统层
通过查看Activity的启动流程可以看出每个activity其实都attach了一个PhoneWindow,而PhoneWindow视图树的根节点是一个ViewRootImpl。而整体绘制其实就是在ViewRootImpl的
performTraversals方法调用后,采用深度优先挨个遍历视图中的子view,通过调用子view的onMesure,onLayout和draw方法,计算出它们的大小、位置。至于为何采用深度优先遍历,是因为子view的位置和大小依赖父view,就像我们使用match_parent属性就是依赖父view的宽高。
这里需要注意的是,draw绘制分为cpu和gpu绘制,cpuz绘制又叫软件绘制,gpu又叫硬件绘制。cpu绘制速度慢,兼容性好,gpu绘制速度快,但是兼容性差,占用内存高(8m以上),在android3.0之后才引入了gpu绘制,但是目前还是有很多Opengl接口不支持硬件加速

(3)系统层:service
Android是通过系统层进程SurfaceFlinger服务来把收到的应用层图层数据渲染到屏幕上
主要工作有:
①响应客户端事件,创建Layer与客户端的surface进行连接
②接收客户端数据及属性,修改layer属性,如颜色、尺寸、透明度
③将创建的layer内容刷新到屏幕上
④维护layer的序列(缓冲),并对layer的最终输出做裁剪计算
(4)应用层和系统层通信:简单说就是应用层绘制到缓冲区,SurfaceFlinger把缓存数据渲染到屏幕,两个进程使用安卓匿名共享内存SharedClient缓存需要显示的数据。
由于应用层和系统层分别是两个不同的进程,需要使用跨进程通信来实现数据传输,在Android显示系统中,使用了内部匿名共享内存ShareClient。每一个应用和SurfaceFlinger都会创建一个SharedClient。每个SharedClient中最多可以创建31个SharedBufferStack(window),也就是是说每个应用理论上最多支持31个window,同时每个SharedBufferStack包含2个(<4.1)缓冲区到3个(>=4.1)缓冲区
(5)显示刷新机制:简单说4.1以前无vsync同步机制,绘制时间分散,很可能绘制任务在,vsync信号后16ms末尾才开始,这样就导致帧率很低,4.0以后采用vsync机制,Choreographer强制vsync执行绘制任务,绘制时间得到保证
Android绘制UI采用双缓冲机制,就是SharedBufferStack中的缓冲区,UI总是先在Back Buffer计算完毕后,再交换到Front Buffer渲染到屏幕上。理想情况下一个刷新在16ms内完成(60fps).
4.1之前是双缓冲,4.1之后是3缓冲Tripple Buffer。并不是缓冲区越多越好,只有绘制占用的cpu和gpu时间片都小的时候3缓冲的性能大概率高于双缓冲。
(6)总结
①影响绘制的根本原因:
<1>绘制任务太重,绘制一帧内容耗时太长;
<2>主线程太忙了,导致vsync信号来的时候还没计算好数据导致丢帧;
(7)开发中优化建议:
①主线程不要做耗时操作,如大量的cursor操作和ams操作,执行复杂算法;
②降低gc几率,图片加载优化,避免创建大量对象;
③io密集型任务放在子线程执行
④cpu密集型任务在子线程中串行执行

from android-daily-interview.

nealkafuly avatar nealkafuly commented on May 22, 2024 4

为什么要问这些题目,对项目的优化有作用吗,艹,别乱加面试题好吗,

from android-daily-interview.

siren4 avatar siren4 commented on May 22, 2024 2

1.界面上的任何一个view的刷新请求最终都是调用ViewRootImpl的scheduleTraversals()来实现的。
2.scheduleTraversals() 会先过滤掉同一帧内的重复调用,确保同一帧内只需要安排一次遍历绘制 View 树的任务.
3.scheduleTraversals() 会往主线程的消息队列中发送一个同步屏障,发完同步屏障后 scheduleTraversals() 将 doTraversal() 封装到 Runnable 里面,然后将这个 Runnable 任务以当前时间戳放进一个待执行的队列里,并且向底层订阅下一个屏幕刷新信号Vsync.
4.当下一个屏幕刷新信号发出时,底层就会回调取出之前放进待执行队列里的任务来执行,也就是ViewRootImpl的doTraversal() 操作。
5.doTraversal()中首先移除同步屏障,再会调用performTraversals() 方法根据当前状态判断是否需要执行performMeasure() 测量、perfromLayout() 布局、performDraw() 绘制流程,在这几个流程中都会去遍历 View 树来刷新需要更新的View。
6.等到下一个Vsync信号到达,将上面计算好的数据渲染到屏幕上,同时如果有必要开始下一帧的数据处理。

from android-daily-interview.

MoJieBlog avatar MoJieBlog commented on May 22, 2024

我来说下为什么是16.6毫秒刷新一次UI。经常玩游戏的人肯定知道60fps的时候基本上就感觉不到卡顿。这里的60fps就是每秒60帧。1000/60 = 16.666666...所以当手机刷新频率16.6时,用户就不会感到卡顿

from android-daily-interview.

Saturdaycong avatar Saturdaycong commented on May 22, 2024

都会
但UI刷新并不一定是CPU问题,刷新这个动作本身就是CPU和GPU合作完成的,但是如果刷新的数据特别多,GPU需要绘制的内容过多,如果GPU性能跟不上也会造成界面卡顿

from android-daily-interview.

nealkafuly avatar nealkafuly commented on May 22, 2024

这些题目一般不该系统代码,app需要知道jb

from android-daily-interview.

zhouyueyuedsf avatar zhouyueyuedsf commented on May 22, 2024

几个点可以说下:

  1. 屏幕刷新的双缓冲机制(本质上是生产者和消费者关系)
  2. requestLayout/invalidate与onVsync的关系
  3. android中优化相关(键盘弹出对动画的影响等)

from android-daily-interview.

mlinqirong avatar mlinqirong commented on May 22, 2024

16毫秒1帧 1秒60/帧 刷新一次

from android-daily-interview.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.