Android自定义View系列
- Android自定义View注意事项
- Android自定义View之Paint绘制文字和线
- Android自定义View之Canvas
- Android自定义View之图像的色彩处理
- Android自定义View之轻松实现圆角和圆形图片
- Android自定义View之Window、ViewRootImpl和View的三大流程
- Android自定义View之事件分发机制总结
- Android自定义View之requestLayout方法和invalidate方法
双缓冲机制
问题的由来
CPU访问内存的速度要远远快于访问屏幕的速度。如果需要绘制大量复杂的图像时,每次都一个个从内存中读取图形然后绘制到屏幕就会造成多次地访问屏幕,从而导致效率很低。这就跟CPU和内存之间还需要有三级缓存一样,需要提高效率。
第一层缓冲
在绘制图像时不用上述一个一个绘制的方案,而采用先在内存中将所有的图像都绘制到一个Bitmap对象上,然后一次性将内存中的Bitmap绘制到屏幕,从而提高绘制的效率。Android中View的onDraw()方法已经实现了这一层缓冲。onDraw()方法中不是绘制一点显示一点,而是都绘制完后一次性显示到屏幕。
第二层缓冲
onDraw()方法的Canvas对象是和屏幕关联的,而onDraw()方法是运行在UI线程中的,如果要绘制的图像过于复杂,则有可能导致应用程序卡顿,甚至ANR。因此我们可以先创建一个临时的Canvas对象,将图像都绘制到这个临时的Canvas对象中,绘制完成之后再将这个临时Canvas对象中的内容(也就是一个Bitmap),通过drawBitmap()方法绘制到onDraw()方法中的canvas对象中。这样的话就相当于是一个Bitmap的拷贝过程,比直接绘制效率要高,可以减少对UI线程的阻塞。
SurfaceView
在SurfaceView中,我们一般都会开启一个子线程,然后在子线程的run方法中通过SurfaceHolder的lockCanvas方法获取到Canvas进行绘制操作,绘制完以后再通过SurfaceHolder的unlockCanvasAndPost方法释放canvas并提交更改。
SurfaceView的特点
- View主要适用于主动更新的情况下,而SurfaceView主要适用于被动更新,例如频繁的刷新
- View在主线程中对画面进行刷新,而SurfaceView通常会通过一个子线程来进行页面的刷新
- View在绘图时没有使用双缓冲机制,而SurfaceView在底层实现机制中就已经实现了双缓冲机制
SurfaceView的模版代码
//必须实现SurfaceHolder.Callback接口和Runnable接口
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
private SurfaceHolder surfaceHolder;
private Canvas canvas;
//子线程绘制标记
private volatile boolean isDrawing;
public MySurfaceView(Context context) {
super(context);
init();
}
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
setFocusable(true);