SurfaceView双缓冲Demo

最近在使用SurfaceView时发现出现了闪烁现象,上网查询一番,发现是由于SurfaceView的双缓冲机制造成的。关于理论部分,《Surface的一些说明》说明的很透彻,这里就不再重复了,这里用一个具体的例子在其内容进行补充,希望对大家有所帮助。

先看这段代码:

[java]  view plain copy
  1.   
[java]  view plain copy
  1. package com.david.surfaceview;  
  2.   
  3. import java.util.Random;  
  4.   
  5. import android.content.Context;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.Canvas;  
  8. import android.graphics.Color;  
  9. import android.graphics.Paint;  
  10. import android.graphics.Paint.Style;  
  11. import android.util.AttributeSet;  
  12. import android.util.Log;  
  13. import android.view.KeyEvent;  
  14. import android.view.SurfaceHolder;  
  15. import android.view.SurfaceView;  
  16.   
  17. public class DoubleSurfaceViewFlicker extends SurfaceView implements  
  18.         SurfaceHolder.Callback {  
  19.       
  20.     private final static String TAG = "DoubleSurfaceViewFlicker";  
  21.     private SurfaceHolder shd;  
  22.   
  23.     public DoubleSurfaceViewFlicker(Context context) {  
  24.         super(context);  
  25.         init();  
  26.     }  
  27.   
  28.     public DoubleSurfaceViewFlicker(Context context, AttributeSet attrs) {  
  29.         super(context, attrs);  
  30.         init();  
  31.     }  
  32.   
  33.     public DoubleSurfaceViewFlicker(Context context, AttributeSet attrs,  
  34.             int defStyle) {  
  35.         super(context, attrs, defStyle);  
  36.         init();  
  37.     }  
  38.   
  39.     void init() {  
  40.         shd = this.getHolder();  
  41.         shd.addCallback(this);  
  42.     }  
  43.   
  44.     @Override  
  45.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  46.             int height) {  
  47.   
  48.     }  
  49.   
  50.     @Override  
  51.     public void surfaceCreated(SurfaceHolder holder) {  
  52.         width = this.getWidth();  
  53.         height = this.getHeight();  
  54.           
  55.         board = Bitmap.createBitmap(this.getWidth(), this.getHeight(),  
  56.                 Bitmap.Config.ARGB_8888);  
  57.         boardCanvas = new Canvas(board);  
  58.   
  59.         paint = new Paint();  
  60.         paint.setStyle(Style.FILL);  
  61.         paint.setAntiAlias(true);  
  62.   
  63.         drawThread.start();  
  64.     }  
  65.   
  66.     @Override  
  67.     public void surfaceDestroyed(SurfaceHolder holder) {  
  68.         isRunning = false;  
  69.         Log.e(TAG, "*** surfaceDestroyed ***");  
  70.     }  
  71.       
  72.     private int width;  
  73.     private int height;  
  74.     private Boolean isRunning = true;  
  75.     public void setIsRunning(Boolean isRunning) {  
  76.         this.isRunning = isRunning;  
  77.     }  
  78.   
  79.     private Paint paint;  
  80.     private int i = 0;  
  81.   
  82.     Bitmap board = null;  
  83.     Canvas boardCanvas = null;  
  84.   
  85.     Thread drawThread = new Thread() {  
  86.   
  87.         public void run() {  
  88.             while (isRunning) {  
  89.                 long startTime = System.currentTimeMillis();  
  90.                 Random random = new Random(System.currentTimeMillis());  
  91.                 Canvas canvas = null;  
  92.   
  93.                 try {  
  94.                     paint.setColor(Color.rgb(random.nextInt(255),  
  95.                             random.nextInt(255), random.nextInt(255)));  
  96.                     paint.setStrokeWidth(4);  
  97.                     paint.setTextSize(40);  
  98.   
  99.                     String text = "" + i + "";  
  100.                     i++;  
  101.   
  102.                     canvas = shd.lockCanvas();  
  103.                     if (canvas != null && board != null) {  
  104.                         canvas.drawText(text, width/2, height/2, paint);  
  105.                     }  
  106.   
  107.                     Thread.sleep(1000);  
  108.                 } catch (Exception e) {  
  109.                     e.printStackTrace();  
  110.                 } finally {  
  111.                     if (shd != null && canvas != null) {  
  112.                         shd.unlockCanvasAndPost(canvas);  
  113.                     }  
  114.                     long endTime = System.currentTimeMillis();  
  115.                     Log.e(TAG, "*** 2 spend time: " + (endTime-startTime));  
  116.                 }  
  117.             }  
  118.         };  
  119.     };  
  120.   
  121. }  

运行它,大家会发现单数显示在一个画面,双数显示在一个画面,这就是因为SurfaceView的双缓冲机制造成的。因为SurfaceView的2个缓冲区A和B是轮流显示的,所以 单数显示在一个画面,双数显示在一个画面。

解决的方法如下:

[java]  view plain copy
  1. package com.david.surfaceview;  
  2.   
  3. import java.util.Date;  
  4. import java.util.Random;  
  5.   
  6. import android.content.Context;  
  7. import android.graphics.Bitmap;  
  8. import android.graphics.Canvas;  
  9. import android.graphics.Color;  
  10. import android.graphics.Paint;  
  11. import android.graphics.Paint.Style;  
  12. import android.graphics.Path;  
  13. import android.util.AttributeSet;  
  14. import android.util.Log;  
  15. import android.view.KeyEvent;  
  16. import android.view.SurfaceHolder;  
  17. import android.view.SurfaceView;  
  18.   
  19. public class DoubleSurfaceView extends SurfaceView implements  
  20.         SurfaceHolder.Callback {  
  21.     private final static String TAG = "DoubleSurfaceView";  
  22.     private SurfaceHolder shd;  
  23.   
  24.     public DoubleSurfaceView(Context context) {  
  25.         super(context);  
  26.         init();  
  27.     }  
  28.   
  29.     public DoubleSurfaceView(Context context, AttributeSet attrs) {  
  30.         super(context, attrs);  
  31.         init();  
  32.     }  
  33.   
  34.     public DoubleSurfaceView(Context context, AttributeSet attrs, int defStyle) {  
  35.         super(context, attrs, defStyle);  
  36.         init();  
  37.     }  
  38.   
  39.     void init() {  
  40.         shd = this.getHolder();  
  41.         shd.addCallback(this);  
  42.     }  
  43.   
  44.     @Override  
  45.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  46.             int height) {  
  47.   
  48.     }  
  49.   
  50.     @Override  
  51.     public void surfaceCreated(SurfaceHolder holder) {  
  52.         width = this.getWidth();  
  53.         height = this.getHeight();  
  54.           
  55.         board = Bitmap.createBitmap(this.getWidth(), this.getHeight(),  
  56.                 Bitmap.Config.ARGB_8888);  
  57.         boardCanvas = new Canvas(board);  
  58.           
  59.         paint = new Paint();  
  60.         paint.setStyle(Style.FILL);  
  61.         paint.setAntiAlias(true);  
  62.   
  63.         drawThread.start();  
  64.     }  
  65.   
  66.     @Override  
  67.     public void surfaceDestroyed(SurfaceHolder holder) {  
  68.         isRunning = false;  
  69.     }  
  70.   
  71.     private int width;  
  72.     private int height;  
  73.     private Boolean isRunning = true;  
  74.     public void setIsRunning(Boolean isRunning) {  
  75.         this.isRunning = isRunning;  
  76.     }  
  77.   
  78.     private Paint paint;  
  79.     private int i = 0;  
  80.   
  81.     Bitmap board = null;  
  82.     Canvas boardCanvas = null;  
  83.   
  84.     Thread drawThread = new Thread() {  
  85.   
  86.         public void run() {  
  87.             while (isRunning) {  
  88.                 long startTime = System.currentTimeMillis();  
  89.                 Random random = new Random(System.currentTimeMillis());  
  90.                 Canvas canvas = null;  
  91.   
  92.                 try {  
  93.                     paint.setColor(Color.rgb(random.nextInt(255),  
  94.                             random.nextInt(255), random.nextInt(255)));  
  95.                     paint.setStrokeWidth(4);  
  96.                     paint.setTextSize(40);  
  97.                       
  98.                     String text = "" + i + "";  
  99.                     boardCanvas.drawText(text, width/2, height/2, paint);  
  100.                     i++;  
  101.   
  102.                     canvas = shd.lockCanvas();  
  103.                     if (canvas!=null && board!=null) {  
  104.                         canvas.drawBitmap(board, 00null);  
  105.                     }  
  106.                       
  107.                     Thread.sleep(1000);  
  108.                 } catch (Exception e) {  
  109.                     e.printStackTrace();  
  110.                 } finally {  
  111.                     if (shd != null && canvas != null) {  
  112.                         shd.unlockCanvasAndPost(canvas);  
  113.                     }  
  114.                     long endTime = System.currentTimeMillis();  
  115.                     Log.e(TAG, "*** 1 spend time: " + (endTime-startTime));  
  116.                 }  
  117.             }  
  118.         };  
  119.     };  
  120.   
  121. }  

这里我将所有的绘画内容都画在board里,然后使用canvas绘制board,以保证SurfaceView的2个缓冲区的内容一致,所以没有闪烁现象发生


转载于:http://blog.csdn.net/imyfriend/article/details/8033823

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值