android绘制知识--双缓冲绘图技术
来源:互联网 发布:淘宝鼠标经过变换图片 编辑:程序博客网 时间:2024/05/15 05:47
今天我们说下双缓冲绘图技术。其实也没有那么神秘,可以理解为就是一个装载工具,说点接地气的比如搬砖。我们每次可以搬十块砖,从A搬到B,如果是就搬十块我们当然是直接搬过去比较快,但是如果是一百或者一千块呢?你直接搬效率肯定很低,于是我们用身边的小推车一直装上然后推过去。我们的双缓冲技术就是这个“小推车”。
我们知道,我们在绘图时有两样东西是少不了的,一个是Canvas(画布),一个是Paint(画笔)。Canvas提供画各种图形的方法,如画圆(drawCircle),画矩形(drawRect)等等,Paint用来设置画笔的样式,比如笔的粗细,颜色等。每个Canvas内部持有一个Bitmap对象的引用,画图的过程其实就是往这个Bitmap当中写入ARGB信息。
那我们现在考虑一件事情是不是我们调用drawCircle等方法就能立刻画出来了呢
这里我们写个代码测试下
@Override protected void onDraw(Canvas canvas) { canvas.drawRect(rect,mPaint); try { TimeUnit.MILLISECONDS.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } canvas.drawCircle(cx,cy,100,mPaint); }
上面的代码运行显示,矩形和圆同时出来而不是先出矩形然后再出现圆形,这也就说明了并不是我们调用drawCircle等方法就能立刻绘制出来的。这就说明必须要等onDraw方法执行完成之后,才会把数据交给GPU去处理展示。这就是android绘图当中的第一道缓冲,即显示缓冲区。
而所谓的双缓冲,在android绘图中其实就是再创建一个Canvas和对应的Bitmap,然后在onDraw方法里默认的Canvas通过drawBitmap画刚才new的那个bitmap从而实现双缓冲。用代码简单的表述是这样的:
private void init(){ Bitmap bufferBm = Bitmap.create(getWidth,getHeight,Bitmap.Config.ARGB_8888); Canvas bufferCanvas = new Canvas(bufferBm);}private void drawSomething(){ bufferCanvas.drawRect(); bufferCanvas.drawCircle(); ... invalidate();}@Overrideprotected void onDraw(Canvas canvas) { canvas.drawBitmap(bufferBm,0,0,null);}
示意图如下:
这样你可以清晰的看到我们如果只是单纯的换一个图的话简直是画蛇添足,但是我们如果是做画板或者是动态的制造图形的话我们这样就很有必要了就不用每次在ondraw重复的调用绘制方法,这样说有点抽象我给出个点击出现圆形的栗子看看就比较清楚了
没用双缓冲的时候的代码
public class MyView extends View { private Paint mPaint; private List<Point> mPoints; public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(Color.GREEN); setBackgroundColor(Color.WHITE); mPoints = new ArrayList<>(); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action){ case MotionEvent.ACTION_DOWN: mPoints.add(new Point((int)event.getX(),(int)event.getY())); break; case MotionEvent.ACTION_UP: invalidate(); break; } return true; } @Override protected void onDraw(Canvas canvas) { for (Point p : mPoints) { canvas.drawCircle(p.x,p.y,50,mPaint); } }}
用了双缓冲
public class NewMyView extends View { private Paint mPaint; private Canvas mBufferCanvas; private Bitmap mBufferBitmap; public NewMyView(Context context) { super(context); } public NewMyView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(Color.GREEN); setBackgroundColor(Color.WHITE); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action){ case MotionEvent.ACTION_DOWN: if (mBufferBitmap == null) { mBufferBitmap = Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_8888); mBufferCanvas = new Canvas(mBufferBitmap); } mBufferCanvas.drawCircle((int)event.getX(),(int)event.getY(),50,mPaint); break; case MotionEvent.ACTION_UP: invalidate(); break; } return true; } @Override protected void onDraw(Canvas canvas) { if (mBufferBitmap == null) { return; } canvas.drawBitmap(mBufferBitmap,0,0,null); }}
咱们对比下,ondraw
@Override protected void onDraw(Canvas canvas) { for (Point p : mPoints) { canvas.drawCircle(p.x,p.y,50,mPaint); } }//使用双缓冲的 @Override protected void onDraw(Canvas canvas) { if (mBufferBitmap == null) { return; } canvas.drawBitmap(mBufferBitmap,0,0,null); }
没用双缓冲的每次我们点击屏幕绘制圆形的时候会在onDraw()循环调用绘制就好像一块一块的搬砖毫无效率,而我们的双缓冲呢只需绘制一次,其他的绘制都绘制在了mBufferBitmap 就好像装车一样
从上面我们可以得出结论:
- 在绘制数据量较小时,不使用双缓冲,GPU的负荷更低,即绘制性能更高;
- 在绘制数据量较大时,使用双缓冲绘图,绘制性能明显高于不使用双缓冲的情况;
- 使用双缓冲会增加内存消耗。
其实上面的结论也很好理解,就像上面举的搬砖的例子,如果砖少的话,用车来拉明显是划不来的,砖的数量很多的时候,用车来拉就可以节省很多时间,但是用车就要消耗额外的资源,这就需要根据不同的情况做出正确的选择。
- android绘制知识--双缓冲绘图技术
- android双缓冲绘图技术分析
- 双缓冲技术绘图
- 双缓冲技术绘图
- 双缓冲技术绘图
- 双缓冲技术绘图
- 双缓冲技术绘图
- VC双缓冲技术绘图
- MFC绘制动态曲线,用双缓冲绘图技术防闪烁
- MFC绘制动态曲线,用双缓冲绘图技术防闪烁
- MFC绘制动态曲线,用双缓冲绘图技术防闪烁
- MFC绘制动态曲线,用双缓冲绘图技术防闪烁
- MFC绘制动态曲线,用双缓冲绘图技术防闪烁
- android 绘图之双缓冲绘图
- Android SurfaceView双缓冲绘图
- Android SurfaceView双缓冲绘图
- Android 双缓冲绘图机制
- C#绘图双缓冲技术总结
- 异常
- B1004. 成绩排名(20')
- su 和 sudo 命令的区别
- angular-router
- 使用Python来编写一个简单的感知机
- android绘制知识--双缓冲绘图技术
- FAT32文件系统
- 原生js的JSONP跨域请求
- 通过注册表创建右键菜单cmder
- GITHUB客户端的获取(windows版本)
- 使用Java2D改善API的绘制效果
- 正则表达式的应用&按钮可执行状态的改变
- 超完整的Chrome浏览器客户端调试大全
- [读书笔记] 重构改善既有代码的设计(3)