探索App性能优化之绘制优化/UI流畅度优化

2,665 阅读3分钟

一、页面绘制对App性能的影响

绘制性能主要影响 :App的页面显示速度。

绘制影响性能的实质:页面的测量 & 绘制时间,一个页面通过递归完成测量 & 绘制过程。

二、绘制优化思路和方向

思路:View的onDraw()要避免执行大量的操作

方向:降低View.onDraw()的复杂度 & 避免过度绘制(Overdraw)

三、绘制优化具体方案

(一) 降低View.onDraw()的复杂度

1、onDraw()中不要创建新的局部对象

因为onDraw())可能会被频繁调用,这样一瞬间产生大量的临时对象,不仅占用了过多的内存而且还导致系统更加频繁gc,降低了程序的执行效率。

2、onDraw()不要做耗时操作

不要执行成千上万的循环操作,尽管每次循环都是轻量级的,但是大量的循环仍然十分抢占CPU的时间片,这会造成view绘制不流畅出现UI卡顿现象(后面会针对UI卡顿做详细说明)。View的绘制帧率保证60fps,即每帧的绘制时间不超过16ms(16ms = 1000/60)。

(二) 避免过度绘制(Overdraw)

1、移除默认的Window背景background
  • 问题描述:应用程序默认继承的主题windowBackground,如默认的Light主题。一般情况下,该默认的Window背景基本用不上,因为背景都自定义设置。若不移除,则导致所有界面都多1次绘制。
<style name="Theme.Light">
    <item name="isLightTheme">true</item>
    <item name="windowBackground">@drawable/screen_background_selector_light</item>
    ...
</style>
  • 解决方案:移除默认的Window背景
方式1:在应用的主题中添加如下的一行属性
<item name="android:windowBackground">@android:color/transparent</item>
 <!-- 或者 -->
<item name="android:windowBackground">@null</item>

方式2:在BaseActivity的onCreate()中使用下面的代码移除
getWindow().setBackgroundDrawable(null);
 <!-- 或者 -->
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
2、移除控件中不必要的背景
  • 场景1:RecyclerView/ListView与item

列表页(RecyclerView/ListView)与其子控件(item)的背景相同都是白色,故可移除子控件(item)布局中的背景。

  • 场景2:ViewPager与Fragment

1个ViewPager + 多个Fragment组成的首页界面,若每个Fragment都设有背景色,即ViewPager 则无必要设置,可移除。

3、减少布局文件的层级(嵌套)
  • 使用布局标签<merge/><ViewStub/><include/>
  • 合适选择布局类型(LinearLayout/RelativeLayout)

四、UI流畅度优化

(一) UI卡顿原因

View的绘制帧数保持60fps是最佳,这要求每帧的绘制时间不超过16ms(1000/60),如果安卓不能在16ms内完成界面的渲染,那么就会出现卡顿现象。

(二) UI卡顿的原因分析

  • 1、在UI线程中做轻微的耗时操作,导致UI线程卡顿
  • 2、布局Layout过于复杂,无法在16ms内完成渲染
  • 3、同一时间动画执行的次数过多,导致CPU和GPU负载过重
  • 4、overDraw,导致像素在同一帧的时间内被绘制多次,使CPU和GPU负载过重
  • 5、View频繁的触发measure、layout,导致measure、layout累计耗时过多和整个View频繁的重新渲染
  • 6、频繁的触发GC操作导致线程暂停,会使得安卓系统在16ms内无法完成绘制
  • 7、冗余资源及逻辑等导致加载和执行缓慢
  • 8、ANR

(二) UI卡顿的优化

1、布局优化
  • 用include、ViewStub、merge
  • 不要出现过于嵌套和冗余的布局
  • 使用自定义View取代复杂的View
2、ListView优化
  • 复用convertView
  • 滑动不加载
3、背景和图片优化
  • 缩略图
  • 图片压缩
4、避免ANR
  • 不要在UI线程中做耗时操作