1.性能优化
1.1 绘制优化
绘制原理:
应用层把经过测量,布局,绘制后的surface缓存数据,
通过进程间通信把数据传递到系统服务层SurfaceFlinger,
SurfaceFlinger通过显示刷新机制把数据渲染到屏幕上。
1.1.1 应用层
1).onMeasure():用深度优先原则递归得到所有View的宽、高;获取当前View的正确宽度
childWidthMeasureSpec和childHeightMeasureSpec之后,可以调用它的成员函数Measure来设置它的大小。
若子View是一个ViewGroup,那么它又会重复执行操作,直到它的所在子孙View的大小都测量完成为止。
2).onLayout():用深度优先原则递归得到所有View的位置;当一个子View在应用程序窗口左上角的位置确定之后,
再结合它在前面测量过程中确定的宽度和高度,就可以完全确定它在应用程序窗口中的布局。
3).onDraw():Android支持两种绘制方式:软件绘制(CPU)和硬件绘制(GPU,要求>= Android3.0)。
硬件加速在UI的显示和绘制的效率远远高于CPU绘制;
但硬件也有明显缺点:
耗电:GPU功耗比CPU高;
兼容问题:某些接口和函数不支持硬件加速;
内存大:使用OpenGL的接口至少需要8MB内存。
1.1.2 系统层
SurfaceFlinger的主要工作是:
1).响应客户端事件,创建Layer与客户端的Surface建立连接。
2).接收客户端数据及属性,修改Layer属性,如尺寸、颜色、透明度等。
3).将创建的Layer内容刷新到屏幕上。
4).维持Layer的序列,并对Layer最终输出做出裁剪计
1.1.3 进程间通信
通信方式:匿名共享内存ShareClient;
每一个应用和SurfaceFlinger之间都会创建一个SharedClient,
每个SharedClient中,最多可以创建31个SharedBufferStack,
每个Surface都对应一个SharedBufferStack,也就是一个window。
这意味着一个Android应用程序最多可以包含31个窗口,
同时每个SharedBufferStack中又包含两个(<4.1)或三个(>=4.1)缓冲区。
总结:应用层绘制到缓冲区,SurfaceFlinger把缓存区数据渲染到屏幕,
两个进程之间使用匿名共享内存SharedClient缓存需要显示的数据。

1.1.4 显示刷新机制
Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,就能达到流畅画面所需要的60FPS;
Android4.1版本对显示系统进行了重构,引入了三个核心元素:VSYNC, Tripple Buffer和Choreographer:
1).VSYNC(Vertical Synchronization 垂直同步):是一种定时中断,一旦收到VSYNC信号,CPU就开始处理各帧数据;
2).Tripple Buffer是显示数据的缓冲区;
3).Choreographer起调度作用,将绘制工作统一到VSYNC的某个时间点上,使应用的绘制工作有序进行;
4).帧数(FPS:Frames Per Second):1s时间里传输的图片的量,即图形处理器每秒能够刷几次;
5).16ms:人类在看画面时,画面在60fps时不会感到卡顿,低于60fps会感到卡顿;
若想要画面保持在60fps,需要屏幕在1s内刷新60次,即16ms刷新一次;
1.1.5 卡顿根因
1).layout复杂,不能在16ms内完成渲染,导致丢帧;
2).View的过度绘制,导致某些像素在同一帧时间内被绘制多次;
3).动画在同一时间执行次数过多,导致CPU或GPU负载过重;
4).UI线程处理耗时操作;
5).GC回收及频繁的GC产生大量的暂停时间;
1.1.6 定位分析工具
1.Profile GPU Rendering 用于查找渲染有问题的界面
橙色:处理时间,柱高,表明GPU很繁忙;
红色:执行时间,进行2D渲染Display list的时间,红高,可能重新提交了视图导致;
蓝色:测量绘制时间,需要长时间去创建和更新DisplayList,蓝高,可能需要重新绘制,or View的ondraw方法处理的事太多;
2.Hierarchy Viewer 用于检查布局嵌套和绘制的时间
layout time按钮:被选中的View给出了Measure,layout,Draw的耗时;
绿色:表示比其他50%view的同阶段速度要快;
黄色:表示比其他50%view同阶段速度要慢;
红色:表示比其他view同阶段都要慢;
出现红色就要注意了,若想查看View的具体耗时,点击View就好了;
3.Systrace 用于性能数据采样和分析
1.跟踪系统的I/O操作
2.内核工作队列
3.CPU负载情况
4.各种子系统的运行情况等
5.对于UI显示性能:如动画播放不流畅,渲染卡顿等提供了分析数据
Alert区域:标记出性能有问题的点及详细描述,如:View在Measure layout耗费了大量时间,导致出现jank(同一帧画了多次),给出的建议是:避免在动画播放期间控制布局;
cpu区域:给出了运行的线程和进程,开启时间,和持续时间等信息;
应用区域:给出了Frames分析;
每一帧就是一个园圈,三种颜色;
绿色:渲染流畅
黄色及红色代表渲染时间超过16ms,红色更严重一些;
4.traceview 用于数据采集和分析 分析trace文件
1.单次执行耗时的方法
2.执行次数多的方法
使用:
1.AS tool中操作
2.代码中Debug.startMethodTracing stop
3.分析:如Incl Real time 查看真正的耗时时间;
1.1.7 优化策略
1.合理使用LinerLayout,RelativeLayout,FrameLayout,ConstraintLayout等布局容器
2.使用<include>标签来进行布局复用
3..使用<merge>标签去除多余层级
4.使用ViewStub来提高加载速度
5.避免GPU过度绘制
1.在XML布局中,控件有重叠且都有设置背景
2.View的onDraw()方法在同一区域绘制多次
1.移除不需要的background
2.在自定义View的onDraw()方法中,用canvas.clipRect()来指定绘制的区域,防止重叠的组件发生过度绘制
3.启动优化
UI布局:应用一般会有闪屏页,优化闪屏页的UI布局,可通过Profile GPU Rendering检测丢帧情况;
启动加载数据逻辑优化:可采用分部加载,异步加载,延期加载策略来提高应用启动速度
数据准备:数据初始化分析,加载数据可考虑用线程初始化等策略
4.合理的刷新机制
尽量减少刷新次数
尽量避免后台有高的CPU线程运行
缩小刷新区域