(TOP)Android性能--记一次简单的重绘优化

我都不知道我有多久没写博客了,真的不是我懒啊,实在是这阵子为了工作和一些乱七八糟的事情搞得晕头转向的,这次我借着周末一点空余时间给我的TT日程管理做了一点优化,这里记录一个重绘的优化。

因为是3.1.0版本的功能,现在市场上还只是3.0.2版本,所以除了本文,应该下载不到新版的。

提供一个3.1.0预览版吧:tl-3.1.0-preview-20160119.apk

一直想整理一份性能优化的文章集合,网上关于这方面的资料很多,但是不是说特别全面和深入,这个事情是我下个阶段的学习重点。

不多说,开始我们的优化过程。

TT日程管理说实话并不需要优化,毕竟不是很大的应用,整个应用也没几张图片,但是作为自己用于学习实验的项目,自然性能优化也要从这里着手。

虽说只是一个小小的重绘优化,不过因为需要应用到实际的项目中,所以还是花了一点时间的,首先看下应用的一个预览,我想让列表头部,也就是日历和标题拥有一个背景图,像下面这样:

看不见视频的地址在这儿:TT日程管理演示

点击中间的日期可以展开或者收起日历,背景图可以根据每个月来决定图片的,比如12月份是滑雪图,3月是早春图…

首先我们打开手机重绘选项,路径是

开发者选项 -> 调试GPU过度渲染(或者类似名称) -> 显示过度渲染区域

没优化之前的重绘情况是这样的:

calendar_header_unop1.png

可以看到头部图片多余的部分是绿色的(因为颜色叠加,所以可能看上去不算很绿),就是上图框出来的部分。

那么我现在不想要这样,我想让显示不出来的这部分不绘制,以节省部分绘制时间,我们需要一个api,就是

canvas.clipRect()

Intersect the current clip with the specified rectangle, which is expressed in local coordinates.
也就是说用来与指定的矩形相交的地方进行裁剪。

怎么使用?

首先我把头部图片的控件重写一下,原来是ImageView,现在替换成自定义的View,称为CalenderHeaderBg,继承ImageView。全部代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class CalenderHeaderBg extends ImageView {

public CalenderHeaderBg(Context context) {
super(context);
}

public CalenderHeaderBg(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void onDraw(Canvas canvas) {
if (getDrawable() == null) {
return;
}
canvas.save();
L.i("CalenderHeaderBg width:" + getWidth() + " height:" + getHeight() + " bottom:" + mBottom);
canvas.clipRect(0, 0, getWidth(), mBottom == 0 ? getHeight() : mBottom);
getDrawable().draw(canvas);
canvas.restore();
}

private int mBottom;

public void clipBottom(int bottom) {
this.mBottom = bottom;
ViewUtil.postViewInvalidate(this);
}
}

我不太想讲canvas的基本操作。

这里我主要重写了ondraw,这里我拿到canvas之后裁剪了一块,这一块多大呢?宽度就是原来的大小,但是高度是类外部指定的,这样之后,系统每次绘制这个view的时候只需要绘制我裁剪之后的那部分内容即可。

GPU主要用于栅格化绘制内容,这是很耗时的操作,CPU把这部分裁剪掉可以大大缓解GPU的压力。

使用这样的一个自定义View替换掉原来的ImageView之后,我们只需要监听头部高度变化,然后用头部的高度来指定背景的高度,达到背景超出部分不重复绘制的目的。

优化之后的重绘情况如图:

calendar_header_oped1.png

可以看到背景超出头部区域已经没有重绘了。

因为这一点的优化并不会带来特别明显的性能上的提升,所以查看性能的一些工具并不能看出明显的区别。但是!很多时候优化就是一点点的积累,不是吗?

Ok,写完收工~