专栏名称: 程序员大咖
为程序员提供最优质的博文、最精彩的讨论、最实用的开发资源;提供最新最全的编程学习资料:PHP、Objective-C、Java、Swift、C/C++函数库、.NET Framework类库、J2SE API等等。并不定期奉送各种福利。
目录
相关文章推荐
程序猿  ·  传字节跳动内部开始禁用Cursor了 ·  3 天前  
逸言  ·  怎么看待AI辅助编程 ·  2 天前  
程序员的那些事  ·  Redis 之父亲证:人类程序员仍力压 ... ·  3 天前  
程序员的那些事  ·  重写太成功反遭封杀!CTO 用 6 个月把 ... ·  2 天前  
蚂蚁技术AntTech  ·  下一代推理模型大猜想 ·  2 天前  
51好读  ›  专栏  ›  程序员大咖

【推荐】Android APP性能优化的四个方面最全总结

程序员大咖  · 公众号  · 程序员  · 2018-05-15 10:24

正文

请到「今天看啥」查看全文


这4种卡顿场景的根本原因可以分为两大类:

  • 界面绘制。主要原因是绘制的层级深、页面复杂、刷新不合理,由于这些原因导致卡顿的场景更多出现在UI和启动后的初始界面以及跳转到页面的绘制上。

  • 数据处理。导致这种卡顿场景的原因是数据处理量太大,一般分为三种情况,一是数据在处理UI线程,二是数据处理占用CPU高,导致主线程拿不到时间片,三是内存增加导致GC频繁,从而引起卡顿。

引起卡顿的原因很多,但不管怎么样的原因和场景,最终都是通过设备屏幕上显示来达到用户,归根到底就是显示有问题,所以,要解决卡顿,就要先了解Android系统的显示原理。

Android系统显示原理

Android显示过程可以简单概括为:Android应用程序把经过测量、布局、绘制后的Surface缓存数据,通过SurfaceFlinger把数据渲染到显示屏幕上, 通过Android的刷新机制来刷新数据。也就是说应用层负责绘制,系统层负责渲染,通过进程间通信把应用层需要绘制的数据传递到系统层服务,系统层服务通过刷新机制把数据更新到屏幕上。

我们都知道在Android的每个View绘制中有三个核心步骤:Measure、Layout、Draw。具体实现是从 ViewRootImp类的performTraversals() 方法开始执行,Measure和Layout都是通过递归来获取View的大小和位置,并且以深度作为优先级,可以看出层级越深、元素越多、耗时也就越长。

真正把需要显示的数据渲染到屏幕上,是通过系统级进程中的SurfaceFlinger服务来实现的,那么这个SurfaceFlinger服务主要做了哪些工作呢?如下:

  • 响应客户端事件,创建Layer与客户端的Surface建立连接。

  • 接收客户端数据及属性,修改Layer属性,如尺寸、颜色、透明度等。

  • 将创建的Layer内容刷新到屏幕上。

  • 维持Layer的序列,并对Layer最终输出做出裁剪计算。

既然是两个不同的进程,那么肯定是需要一个跨进程的通信机制来实现数据传递,在Android显示系统中,使用了Android的匿名共享内存:SharedClient,每一个应用和SurfaceFlinger之间都会创建一个SharedClient ,然后在每个SharedClient中,最多可以创建31个 SharedBufferStack,每个Surface都对应一个SharedBufferStack,也就是一个Window。

一个SharedClient对应一个Android应用程序,而一个Android应用程序可能包含多个窗口,即Surface。也就是说SharedClient包含的是SharedBufferStack的集合,其中在显示刷新机制中用到了双缓冲和三重缓冲技术。最后总结起来显示整体流程分为三个模块:应用层绘制到缓存区,SurfaceFlinger把缓存区数据渲染到屏幕,由于是不同的进程,所以使用Android的匿名共享内存SharedClient缓存需要显示的数据来达到目的。

除此之外,我们还需要一个名词:FPS。FPS表示每秒传递的帧数。在理想情况下,60FPS就感觉不到卡,这意味着每个绘制时长应该在16ms以内。但是 Android系统很有可能无法及时完成那些复杂的页面渲染操作。Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需的60FPS。如果某个操作花费的时间是24ms ,系统在得到VSYNC信号时就无法正常进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面,这种现象在执行动画或滑动列表比较常见,还有可能是你的Layout太过复杂,层叠太多的绘制单元,无法在16ms完成渲染,最终引起刷新不及时。

卡顿根本原因

根据Android系统显示原理可以看到,影响绘制的根本原因有以下两个方面:

  • 绘制任务太重,绘制一帧内容耗时太长。

  • 主线程太忙,根据系统传递过来的VSYNC信号来时还没准备好数据导致丢帧。

绘制耗时太长,有一些工具可以帮助我们定位问题。主线程太忙则需要注意了,主线程关键职责是处理用户交互,在屏幕上绘制像素,并进行加载显示相关的数据,所以特别需要避免任何主线程的事情,这样应用程序才能保持对用户操作的即时响应。总结起来,主线程主要做以下几个方面工作:

  • UI生命周期控制

  • 系统事件处理

  • 消息处理

  • 界面布局

  • 界面绘制

  • 界面刷新

除此之外,应该尽量避免将其他处理放在主线程中,特别复杂的数据计算和网络请求等。

性能分析工具

性能问题并不容易复现,也不好定位,但是真的碰到问题还是需要去解决的,那么分析问题和确认问题是否解决,就需要借助相应的的调试工具,比如查看Layout层次的Hierarchy View、Android系统上带的GPU Profile工具和静态代码检查工具Lint等,这些工具对性能优化起到非常重要的作用,所以要熟悉,知道在什么场景用什么工具来分析。

1,Profile GPU Rendering

在手机开发者模式下,有一个卡顿检测工具叫做:Profile GPU Rendering,如图:

它的功能特点如下:

  • 一个图形监测工具,能实时反应当前绘制的耗时

  • 横轴表示时间,纵轴表示每一帧的耗时

  • 随着时间推移,从左到右的刷新呈现

  • 提供一个标准的耗时,如果高于标准耗时,就表示当前这一帧丢失







请到「今天看啥」查看全文