^-^

^-^

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五个奇数数字,原因是最后绘制的是带有这些奇数的那张缓冲画布,而所有的偶数数字将绘制到另一张缓冲画布上。

 


 

阅读更多
版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/tobacco5648/article/details/8261749
个人分类: Android日记
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭