Android进阶之视图优化篇

今天来分析一下视图优化,首先解释一下GPU过度绘制的概念,GPU过度绘制指的是在屏幕一个像素上绘制多次(超过一次),比如一个TextView后有背景,那么显示文本的像素至少绘了两次,一次是背景,一次是文本。
颜色标识: GPU过度绘制从好到差:蓝-绿-淡红-红
  • 蓝色1x过度绘制
  • 绿色2x过度绘制
  • 淡红色3x过度绘制
  • 红色超过4x过度绘制
GPU过度绘制或多或少对性能有些影响,所以我们应该尽量不要让我们的界面不要出现红色,否则对性能影响很大,影响用户体验。
Android进阶之视图优化篇_第1张图片
过度绘制级别
准备工具:
  • Android 4.2+设备
  • Android Studio 1.5+
  • AndroidUIPorblems下载地址
开始分析:

1.首先在开发者选项中把GPU过度绘制打开,运行项目,查看效果。


Android进阶之视图优化篇_第2张图片
开启GPU OverDraw

可以看到屏幕上的颜色,分别代表了上面所说的过度绘制级别,非常直观的显示了问题所在,现在我们直奔代码,开始进行优化修改。


Android进阶之视图优化篇_第3张图片
程序首页

由于有窗体默认会有背景色存在,但是我们现在自定义了背景,完全不需要window自带的背景,这时候可以使用getWindow().setBackgroundDrawable(null);把window的背景去除,看起来很不错,颜色比刚才好了一些,接下来继续寻找可以优化的地方。
Android进阶之视图优化篇_第4张图片
第一次修改后的效果

经过寻找唯一可以优化的地方只有TextView控件的背景了,如果没必要,可以去除。这里就不演示修改后的结果了,下面进入OverDrawView看看有什么需要优化的地方,看起来过度绘制现象很严重。


Android进阶之视图优化篇_第5张图片
OverDrawView

看一下绘图的代码,原来在填充矩形时发生重复了,修改一下就OK了,同样不要忘记了把window的背景设置为null;
@Override
protected void onDraw(Canvas canvas) {    
super.onDraw(canvas);   
int width = getWidth();    
int height = getHeight();    
mPaint.setColor(Color.GRAY);    
canvas.drawRect(0, 0, width, height, mPaint);    
mPaint.setColor(Color.CYAN);    
canvas.drawRect(0, height/4, width, height, mPaint);    
mPaint.setColor(Color.DKGRAY);    
canvas.drawRect(0, height/3, width, height, mPaint);    
mPaint.setColor(Color.LTGRAY);    
canvas.drawRect(0, height/2, width, height, mPaint);
}

代码修改如下:

@Override
protected void onDraw(Canvas canvas) {    
super.onDraw(canvas);   
int width = getWidth();    
int height = getHeight();    
mPaint.setColor(Color.GRAY);    
canvas.drawRect(0, 0, width, height/4, mPaint);    
mPaint.setColor(Color.CYAN);    
canvas.drawRect(0, height/4, width, height/3, mPaint);    
mPaint.setColor(Color.DKGRAY);    
canvas.drawRect(0, height/3, width, height/2, mPaint);    
mPaint.setColor(Color.LTGRAY);    
canvas.drawRect(0, height/2, width, height, mPaint);
}

最终效果如图所示,不存在过度绘制的情况了。


Android进阶之视图优化篇_第6张图片
OverDrawView

最后看一下BusyOnDraw的情况,截图无法展现出效果,因为程序在跳转时会卡住几秒钟,直接看代码,发现在onDraw函数里面做了非常耗时的操作,所以很好解决,开启一个线程做可以了。

@Override
protected void onDraw(Canvas canvas) {    
super.onDraw(canvas);    
for (int i = 0; i < 1000; i++) {        
System.out.println("canvas = [" + canvas + "]" + i);    }    
Paint paint = new Paint();    
paint.setColor(Color.RED);    
paint.setStyle(Paint.Style.STROKE);    
paint.setStrokeWidth(4);    
int radius = Math.min(getWidth(), getHeight()) / 2;    
canvas.drawCircle(getWidth()/2, getHeight()/2, radius, paint);
}

代码修改如下:

  • 成员变量:
private Handler mHandler=new Handler();
private Paint mPaint = new Paint();
  • onDraw:
@Override
protected void onDraw(Canvas canvas) { 
super.onDraw(canvas);    
mHandler.post(doBusyThing(canvas));    
mPaint.setColor(Color.RED);    
mPaint.setStyle(Paint.Style.STROKE);    
mPaint.setStrokeWidth(4);    
int radius = Math.min(getWidth(), getHeight()) / 2;    
canvas.drawCircle(getWidth()/2, getHeight()/2, radius, mPaint);
}
  • 添加doBusyThing方法:
private Runnable doBusyThing(final Canvas canvas){    
return new Runnable() {        
@Override        
public void run() {            
for (int i = 0; i < 1000; i++) {                
System.out.println("canvas = [" + canvas + "]" + i);            
}       
}    
};
}

OK修改完成,这个项目已经没有问题了,这篇文章到此结束了。

你可能感兴趣的:(Android进阶之视图优化篇)