Android提供了View来进行绘图处理,在大部分情况下,View都能满足绘图需求。大家都知道View是通过刷新来重绘视图,Android系统通过发出VSYNC信号来进行屏幕的重绘,刷新的间隔时间为16ms。如果在16ms内View完成了你所需要执行的所有操作,那么用户在视觉上,就不会产生卡顿的感觉;反之,如果操作的逻辑过多时,就会掉帧从而使得用户感觉到卡顿。特别的需要频繁刷新的界面上,如游戏(60FPS以上),就会不断阻塞主线程,从而导致界面卡顿。而Android提供了SurfaceView来解决这种情况。
二、SurfaceView和View的不同之处
SurfaceView和View的不同之处:
View
SurfaceView
适用于主动更新
适用于被动刷新
在主线程中进行画面更新
通常通过一个子线程来进行画面更新
绘图中没有使用双缓冲机制
在底层实现中就实现了双缓冲机制
比较了上面的不同之处,显然可以发现,如果一个View需要频繁的刷新,或者在刷新时数据处理量大(可能引起卡顿),可以考虑使用SurfaceView来替代View。
三、SurfaceView的基本使用
SurfaceView在使用的过程中,有一套模板代码,对于大部分的SurfaceView绘图操作而言都可以套用,因此SurfaceView在使用过程中并不难。
其中值得注意的几个点:。
两个接口
SurfaceHolder.CallBack
Runnable
第一个接口中需要实现的方法分别对应于SurfaceView的生命周期,即创建、改变和销毁。具体代码如下:
//Surface的生命周期 @Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { }
而第二接口需要实现run方法,用于在子线程中进行draw操作。
由于SurfaceView的基本操作比较简单,这边就直接给出了它的一个模板代码
package com.pignet.surfaceviewdemo; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * Created by DB on 2017/6/9. */ public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback,Runnable{ private SurfaceHolder mHolder; private Canvas mCanvas; private boolean mIsDrawing; //构造方法 public SurfaceViewTemplate(Context context) { super(context); initView(); } public SurfaceViewTemplate(Context context, AttributeSet attrs) { super(context, attrs); } public SurfaceViewTemplate(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } private void initView() { mHolder=getHolder(); mHolder.addCallback(this); setFocusable(true); setFocusableInTouchMode(true); this.setKeepScreenOn(true); } @Override public void surfaceCreated(SurfaceHolder holder) { mIsDrawing=true; new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { mIsDrawing=false; } @Override public void run() { while (mIsDrawing){ draw(); //通过线程休眠以控制刷新速度 try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } private void draw() { try { mCanvas=mHolder.lockCanvas(); //初始化画布并在画布上画一些东西 }catch (Exception e){ }finally { //判断画布是否为空,从而避免黑屏情况 if(mCanvas!=null){ mHolder.unlockCanvasAndPost(mCanvas); } } } }
下面结合一个具体的示例,展现SurfaceView在绘图中的效果(绘图板,即通过监听触摸事件完成内容的绘制)。