【Android杂谈】性能优化:渲染

Google在Udacity上发布了《Android Performance》的在线课程,介绍了如何通过工具识别和和修复性能问题。课程分为四节:渲染,计算,内存,耗电。比较系统,难度不高,学完大概6~8个小时。有些内容可能稍有过时(后文会提到官方推荐的新的工具及库),但整体还是非常推荐的。性能是软件最基本的需求之一,每个开发人员都应该学一定的性能优化知识。

刷新率&丢帧

有关渲染最基本的概念是“刷新率”,指的是屏幕在一秒内的更新次数,以Hertz为单位。大部分Android设备的刷新率是60Hz,也就是说屏幕在一秒内更新60次,即每16.6667ms刷新一次屏幕。

如果程序没有在16ms内完成刷新屏幕的逻辑操作,比如下图中UI线程上的操作花费了24ms,就会出现丢帧:即用户在32ms内看到同样的画面。

如果用户这时正在和UI交互,比如滑动窗口或者输入数据,就会有很明显的卡顿感,很容易抱怨App非常“卡”。

CPU & GPU

Android的渲染分为CPU和GPU两部分工作。其中CPU主要负责视图的测量,清除,重建和计算。CPU会通过计算将需要绘制的图形(文字、按钮等)转换成多边形或者纹理,之后通过调用Open GL接口,通过GPU进行栅格化的工作。栅格化是指计算屏幕上的像素点并进行绘制,是一个非常耗时的工作。而从CPU到GPU的数据传输也很耗时。而Android从Honeycomb版本开始对CPU和GPU之间的数据转换和传输做了很多优化,比如很多资源都会预先被打包到GPU之中,避免了绘制时的转换。

Overdraw

虽然Android系统本身在渲染方面做了很多优化,但实际开发中还是会有渲染的性能问题,比如最容易出现的:过度渲染/过度绘制(Overdraw)。

过度绘制描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层级的试图结构中,如果不可见的UI也在做绘制的操作,会导致某些像素区域被绘制了多次,这样就会浪费大量的CPU和GPU资源。

检测Overdraw最简单的办法是通过设置里面Show GPU Overdraw功能:Settings->Developer Options->Hardware accelerated rendering->Debug GPU overdraw->选择show overdraw areas。

颜色的意义:

  • 原色表示没有Overdraw
  • 蓝色:一次Overdraw
  • 绿色:两次Overdraw
  • 粉色:三次Overdraw
  • 红色:四次或者更多的Overdraw

避免Overdraw的方法:

  • 移除布局中不必要的背景:一个不必要的背景可能是永远不可见的。
  • 使用Canvas#clipRect()来帮助系统识别自定义控件的可见区域,可见区域以外的区域在绘制时会被忽视。
  • 使用Canvas#quickReject()判断视图是否和某个矩形相交,从而跳过那些非矩形区域内的绘制操作。

View Hierarcy

除了Overdraw之外,另一个影响渲染性能的问题是视图层级。Android通过DisplayList把XML布局文件转换成GPU可以识别并绘制的对象。DisplayList在某个View第一次需要被渲染时,并通过GPU的绘制指令来进行渲染。如果View的属性发生了改变(例如移动位置),只需要执行DisplayList中的指令就可以完成View的更新。而如果View中的某些组件的内容被修改了,那么之前的DisplayList就无法继续使用了,系统需要重新创建一个DisplayList并重新执行渲染指令更新到屏幕上。

系统在绘制布局时需要进行:

  • 测量(Measurement):测量布局自身以及内部所有子控件
  • 摆放(Positiong):布局测量完成之后,根布局会将他们摆放到合适的位置。

当View的某个属性发生了变化,View自身会调用View#invalidate()方法,自底向上传播该请求,直到根布局。这个流程的表现性能取决于View的复杂程度。举个例子,假设某个Button的尺寸需要放大到两倍,需要通过父View重新测量并摆放其他子View的位置,只是修改一个Button的尺寸,会触发整个HierarcyView的重新测量和摆放。如果布局很复杂,很容易会出现性能问题。

课程中介绍了通过Hierarchy Viewer来显示布局的层次关系,视图组件的各种属性。

但其实Hierarchy Viewer在Android Studio 3.1之后已被标为deprecated,官方推荐Layout Inspector调试视图的层级和性能。

提升布局性能:

  • 核心是尽量保持布局层级的扁平化,避免出现重复的嵌套布局。
  • 比如一些情况下(如课程示例),RelativeLayout相较与LinearLayout更容易减少视图层级。
  • 16年GoogleIO介绍了ConstraintLayout(课程没有介绍),对改善布局性能也有很大帮助。
     

引用

https://cn.udacity.com/course/android-performance--ud825

https://developer.android.google.cn/studio/profile/inspect-gpu-rendering#profile_rendering

https://developer.android.google.cn/studio/profile/hierarchy-viewer

https://developer.android.google.cn/studio/debug/layout-inspector

https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout

(转载请注明作者和出处:http://blog.csdn.net/xiaowei_cqu 未经允许请勿用于商业用途)

猜你喜欢

转载自blog.csdn.net/xiaowei_cqu/article/details/84501286