android安卓-canvas绘制双缓冲

原帖

Android 绘图时实现双缓冲

一、双缓冲技术原理:

  在内存中创建一片内存区域,把将要绘制的图片预先绘制到内存中,在绘制显示的时候直接获取缓冲区的图片进行绘制。更具体一点来说:先通过setBitmap方法将要绘制的所有的图形绘制到一个Bitmap上也就是先在内存空间完成,然后再来调用drawBitmap方法绘制出这个Bitmap,显示在屏幕上。

二、双缓冲技术出现的缘由

  当一个动画争先显示时,程序又在改变它,前面的画面还没显示完,程序又要求重新绘制,这样屏幕就会不停闪烁。为了避免闪烁,使绘制的内容有一个平滑的过度,所以就出现了双缓冲技术——》将要处理的图片都放在内存中处理好后,再将其一次性显示到屏幕上。这样出来的就是完整的图像,不会出现闪烁现象。

二、双缓冲技术的优缺点

  优点:

    1.绘制过程中一般不会出现闪烁现象,能使动画平滑过度。

    2.高效,将图像一次性绘制到屏幕上比一次一次的绘制要高效的多。

  缺点:

    当图片过大时会严重的消耗内存

三、实现双缓冲的步骤

  1.创建一片内存区域用于存放目标Bitmap

  

    // 创建一个200*200的缓冲区
        bitmapBuffer = Bitmap.createBitmap(200, 200, Config.ARGB_8888);

  2.设置目标内容绘制到缓冲区

    // 设置将目标内容绘制在“缓冲区”
        canvas.setBitmap(bitmapBuffer);

  3.把将要绘制的图片绘制到缓冲区 

    // 把将要绘制的图片绘制到缓冲区
        canvas.drawBitmap(bitmap, 0, 0, paint);

  4.在onDraw方法中将缓冲区中的内容绘制到屏幕上

  

    //将缓冲区的图片绘制到屏幕上
        canvas.drawBitmap(bitmapBuffer, 0,0, paint);

四、双缓冲技术的实现代码:备注一下,其实SurfaceView和GLSurfaceView已经实现了双缓冲技术,建议在做动画和游戏时使用这两个view

  1.DoubleBufferingView.java

复制代码
package cn.yw.lib.doublebuffering;

import cn.yw.lib.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;

/**

  • 双缓冲View
  • @author yw-tony

*/
public class DoubleBufferingView extends View implements Runnable {
private Bitmap bitmap = null;
private Paint paint = null;
// 创建一个Bitmap缓冲区
private Bitmap bitmapBuffer;
private Canvas canvas;
public boolean flag = true;// 线程结束标记,默认线程是开启的

<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> DoubleBufferingView(Context context) {
    </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(context);
    initBuffering(context);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 开启线程进行图片绘制</span>
    <span style="color: rgba(0, 0, 255, 1)">new</span> Thread(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">).start();
}

</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
 * 初始化缓冲区
 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> initBuffering(Context context) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 装载资源</span>
    bitmap =<span style="color: rgba(0, 0, 0, 1)"> BitmapFactory.decodeResource(context.getResources(),
            R.drawable.ic_launcher);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个200*200的缓冲区</span>
    bitmapBuffer = Bitmap.createBitmap(200, 200<span style="color: rgba(0, 0, 0, 1)">, Config.ARGB_8888);
    canvas </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Canvas();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置将目标内容绘制在“缓冲区”</span>

canvas.setBitmap(bitmapBuffer);
// 实例化一个画笔
paint = new Paint();
// 把将要绘制的图片绘制到缓冲区
canvas.drawBitmap(bitmap, 0, 0, paint);
}

@Override
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onDraw(Canvas canvas) {
    </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onDraw(canvas);
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将缓冲区的图片绘制到屏幕上</span>
    canvas.drawBitmap(bitmapBuffer, 0, 0<span style="color: rgba(0, 0, 0, 1)">, paint);
    Log.e(</span>"draw", "正在努力绘制!"<span style="color: rgba(0, 0, 0, 1)">);
}

@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> run() {
    </span><span style="color: rgba(0, 0, 255, 1)">while</span><span style="color: rgba(0, 0, 0, 1)"> (flag) {
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            postInvalidate();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 更新View界面</span>
            Thread.sleep(1000<span style="color: rgba(0, 0, 0, 1)">);
        } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
            e.printStackTrace();
        }
    }
}

}

复制代码

2.DoubleBufferingActivity.java

  

复制代码
package cn.yw.lib.doublebuffering;

import android.app.Activity;
import android.os.Bundle;

/**

  • 测试双缓冲
  • @author yw-tony

*/
public class DoubleBufferingActivity extends Activity {
private DoubleBufferingView bufferView;

@Override
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(Bundle savedInstanceState) {
    </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
    bufferView </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> DoubleBufferingView(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
    setContentView(bufferView);
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当用户按下回退键时结束线程</span>

@Override
public void onBackPressed() {
super.onBackPressed();
bufferView.flag = false;
}
}

复制代码
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值