SurfaceView

来源:互联网 发布:故宫淘宝 月饼 编辑:程序博客网 时间:2024/05/21 16:59

View 是通过刷新来重绘视图的,刷新的间隔时间是16ms,如果执行的操作太多,不能够在16ms内完成所有的操作,就会出现不断阻塞主线程,导致卡顿现象.
而SurfaceView是android系统来解决上述问题的,是View的孪生兄弟,其主要区别在于以下几点

  • View主要适用于主动更新,而SurfaceView主要使用被动更新,比如频繁的刷新
  • View是在主线程中对画面进行刷新的,而SurfaceView通常会通过一个子线程来进行页面的刷新
  • View在绘图时没有使用双缓冲机制,而SurfaceView在底层实现机制中实现了双缓冲机制
    总之,View需要频繁刷新或者刷新时需要处理数据比较大时就可以使用SurfaceView来完成.
    使用SurfaceView时,会通过lockCanvas()来获取当前Canvas对象,获取到的Canvas还是继续上次的Canvas对象,不是一个新对象,因此,之前的绘图操作都会被保留下来,可以通过drawColor来进行清屏.另外,绘制完成后,通过unlockCanvasAndPost()方法对画布的内容进行提交.
    举例 画一个正弦曲线 其中有surfaceView的模板框架
public class SurfaceViewDemo extends SurfaceView implements SurfaceHolder.Callback,Runnable{    private Canvas mCanvas;    private SurfaceHolder surfaceHolder;    private boolean isDrawing;//子线程的标志位    private Paint mPaint;    private Path mPath;    private int x = 0,y=0;    public SurfaceViewDemo(Context context) {        super(context);    }    public SurfaceViewDemo(Context context, AttributeSet attrs) {        super(context, attrs);        initView();    }    private void initView() {        mPaint = new Paint();        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeCap(Paint.Cap.ROUND);        mPaint.setStrokeJoin(Paint.Join.ROUND);        mPaint.setStrokeWidth(5);        mPaint.setColor(Color.GREEN);        mPath = new Path();//        mPath.moveTo(0,0);        surfaceHolder = getHolder();        surfaceHolder.addCallback(this);        setFocusable(true);        setFocusableInTouchMode(true);        this.setKeepScreenOn(true);    }    public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        isDrawing = true;        new Thread(this).start();    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {         isDrawing = false;        Log.i("niuniu"," isDrawing " +isDrawing);    }    @Override    public void run() {       while (isDrawing){           draw();           x++;           y = (int)(200*Math.sin(x*2*Math.PI/180)+600);           mPath.lineTo(x,y);       }    }    private void draw() {        try {            mCanvas = surfaceHolder.lockCanvas();            mCanvas.drawColor(Color.GRAY);            mCanvas.drawPath(mPath,mPaint);        }catch (Exception e){            Log.i("niuniu"," error occour " +e.getMessage());            e.printStackTrace();        }finally {            if (mCanvas != null){                surfaceHolder.unlockCanvasAndPost(mCanvas);            }        }    }}

举例2 实现一个绘图板

    @Override    public void run() {        long start = System.currentTimeMillis();        while (isDrawing){            draw();        }        long end = System.currentTimeMillis();        if (end-start <100){            try {                Thread.sleep(100-(end-start));            }catch (InterruptedException e){                e.printStackTrace();            }        }    }    private void draw() {        try {            mCanvas = surfaceHolder.lockCanvas();            mCanvas.drawColor(Color.GRAY);            mCanvas.drawPath(mPath,mPaint);        }catch (Exception e){            Log.i("niuniu"," error occour " +e.getMessage());            e.printStackTrace();        }finally {            if (mCanvas != null){                surfaceHolder.unlockCanvasAndPost(mCanvas);            }        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.i("niuniu"," onTouchEvent ");        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:                mPath.moveTo(event.getX(),event.getY());                break;            case MotionEvent.ACTION_MOVE:                mPath.lineTo(event.getX(),event.getY());                break;        }        return true;    }
原创粉丝点击