Android群英传——第六章SurfaceView

SurfaceView

View通过刷新来重绘视图,Android系统通过发出VSYNC信号来进行屏幕重绘,刷新的间隔为16ms。如果在16ms内View完成了你所需要执行的所有操作。那么用户在视觉上就不会产生卡顿的感觉;而如果执行的操作逻辑太多,特别是需要频繁的刷新界面上,例如游戏界面, 那么就会不断的阻塞主线程,从而导致画面卡段。

Skipped 47 frames!The Application may be doing too much work on its main thread

这个警告的产生,很多情况下就是因为在绘制过程中,处理太多逻辑造成的。
所以SurfaceView就产生了。
SurfaceView继承自View,已知的直接子类有GLSurfaceView和VideoView,都是需要频繁刷新的View

区别:
- View主要用于主动更新的情况,SurfaceView主要用于被动更新,比如频繁的刷新操作
- View在主线程中对画面进行刷新,而SurfaceView通过一个子线程进行页面的刷新
- View没有双缓冲机制,而SurfaceView在底层实现机制中已经实现双缓冲机制

双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。

如果你的自定义View需要频繁的刷新,或者刷新时数据处理量较大,就可以使用SurfaceView来取代View

使用SurfaceView绘制正弦曲线:
这里写图片描述
code:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Created by feathers on 16-11-18.
 */

public class SurfaceViewDemo extends SurfaceView implements SurfaceHolder.Callback,Runnable{

    // SurfaceHolder
    private SurfaceHolder mHolder;

    // 用于绘图的Canvas
    private Canvas mCanvas;

    //子线程标志位
    private boolean mIsDrawing;

    private int x = 0;
    private int y = 0;
    private Path mPath;
    private Paint mPaint;

    public SurfaceViewDemo(Context context) {
        this(context, null);
    }

    public SurfaceViewDemo(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    private void initView() {
        // 初始化SurfaceHolder,并注册SurfaceHolder的回调方法
        mHolder = getHolder();
        mHolder.addCallback(this);

        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setKeepScreenOn(true);
//        mHolder.setFormat(PixelFormat.OPAQUE);

        mPath = new Path();
        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(10);
    }

    // SurfaceView创建
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        // 被创建后启动一个新的线程用来绘制
        mIsDrawing = true;
        new Thread(this).start();
    }

    // SurfaceView改变
    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {

    }

    // SurfaceView销毁
    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        // 销毁后,子线程结束
        mIsDrawing = false;
    }

    @Override
    public void run() {
        while (mIsDrawing) {
            draw();
            x += 1;
            y = (int) (100 * Math.sin(x * 2 * Math.PI / 180) + 400);
            mPath.lineTo(x, y);
        }
    }

    private void draw() {
        try {
            // 获取Canvas
            mCanvas = mHolder.lockCanvas();
            // SurfaceView背景
            mCanvas.drawColor(Color.WHITE);
            mCanvas.drawPath(mPath, mPaint);
        } catch (Exception e) {

        }finally {
            if (mCanvas != null) {
                mHolder.unlockCanvasAndPost(mCanvas);
            }
        }

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        this.mCanvas = canvas;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值