SurfaceView闪烁问题的根源-双缓存机制
上篇中提到了SurfaceView绘制触摸轨迹时出现的闪烁问题,这里就说明下产生这种困扰的根源——双缓存机制。
Android中的SurfaceView在更新视图时,为了提高更新效率,加强用户体验,采用了双缓存机制。
Android的官方说明有:
Note: On each pass you retrieve the Canvas from the SurfaceHolder, the previous state of the Canvas will be retained. In order to properly animate your graphics, you must re-paint the entire surface. For example, you can clear the previous state of the Canvas by filling in a color with drawColor() or setting a background image with drawBitmap(). Otherwise, you will see traces of the drawings you previously performed.
在运用时可以理解为:SurfaceView在更新视图时用到了两张Canvas,一张frontCanvas和一张backCanvas,每次实际显示的是frontCanvas,backCanvas存储的是上一次更改前的视图,当使用lockCanvas()获取画布时,得到的实际上是backCanvas而不是正在显示的frontCanvas,之后你在获取到的backCanvas上绘制新视图,再unlockCanvasAndPost(canvas)此视图,那么上传的这张canvas将替换原来的frontCanvas作为新的frontCanvas,原来的frontCanvas将切换到后台作为backCanvas。例如,如果你已经先后两次绘制了视图A和B,那么你再调用lockCanvas()获取视图,获得的将是A而不是正在显示的B,之后你讲重绘的C视图上传,那么C将取代B作为新的frontCanvas显示在SurfaceView上,原来的B则转换为backCanvas。
如下面的一段代码:
package com.tobacco.touchdraw;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;public class TestView extends SurfaceView implements Callback{
private SurfaceHolder sfh;
private Canvas canvas;
private Paint paint;public TestView(Context context) {
super(context);
sfh=this.getHolder();
sfh.addCallback(this);
paint=new Paint();
paint.setColor(Color.RED);
paint.setAntiAlias(true);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
}@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}@Override
public void surfaceCreated(SurfaceHolder holder) {
for(int i=0;i<10;i++){
canvas=sfh.lockCanvas();
if(canvas!=null){
canvas.drawText(""+i,10,20*i,paint);
}
sfh.unlockCanvasAndPost(canvas);
}
}@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}}
最终在屏幕上显示的,不会是0到9的10个数字,而是1,3,5,7,9五个奇数数字,原因是最后绘制的是带有这些奇数的那张缓冲画布,而所有的偶数数字将绘制到另一张缓冲画布上。
更多相关文章
- Android之使用AchartEngineActivity引擎绘制柱状图、曲线图
- ANDROID L——RecyclerView,CardView导入和使用
- Android(安卓)Cavans 基础应用
- Android(安卓)ViewPager初探:让页面滑动起来
- 【android之锚定视图】
- android 开发-Toast控件的实现
- cocos2dx 遮罩层 android 手机上 失败
- Mono for Android(安卓)实现高效的导航
- Android(安卓)Gallery3d源码学习总结(二)——绘制流程drawThumbnai