Android 系统提供了 View 进行绘图处理,View 可以满足大部分的绘图需求,但在某些时候,View 通过刷新来重绘视图,Android 系统通过发出 vsync 信号来进行屏幕重绘,刷新的间隔时间为 16ms,如果在这个时间间隔内完成了你所需要执行的所有操作,那么在视觉上,就不会产生卡顿的感觉,而如果执行的操作逻辑太多,特别再需要频繁刷新的界面上,例如游戏界面,那么就会不断阻塞主线程,从而导致界面卡顿,为了避免这个问题,Android 系统提供了 surfaceView 组件来解决这个问题。surfaceView 和 View 的区别主要有下面几点:
- View 主要适用于主动更新的情况,而 surfaceView 主要适用于被动更新,例如频繁的刷新。
- View 在主线程中对画面进行刷新,而 surfaceView 通常会通过一个子线程来进行页面的刷新
- View 在绘图时没有使用双缓冲机制,而 surfaceView 在底层实现机制上就已经实现了双缓冲机制。
总结就是,如果你的自定义 View 需要频繁刷新,或者刷新时数据处理量很大,考虑用 SurfaceView 来替代 View。
surfaceView 的使用
- 创建 SurfaceView,一般我们实现
SurfaceHolder.Callback, Runnable
接口
//surfaceView 的创建
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsDraw = true;
}
//surfaceView 的改变
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
//surfaceView 的销毁
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsDraw = false;
}
//runnable 的run 方法中,我们可以执行绘制的操作
@Override
public void run() {
while (mIsDraw) {
draw();
}
}
- 初始化 surfaceView
mHolder = getHolder();
mHolder.addCallback(this);
//通过 lockCanvas 方法可以获得当前的 canvas 绘图对象,接下来,就可以与在 View 中进行的绘制操作一样了
mCanvas = mHolder.lockCanvas();
//通过 unlockCanvasAndPost 方法可以对当前画布内容进行提交。
mHolder.unlockCanvasAndPost(mCanvas);
下面是一个 surfaceView 使用的模板,基本上可以在这个基础上来修改满足大部分的绘图需求。
public class SurfaceViewDemo extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder mHolder;
private boolean mIsDraw;
private Canvas mCanvas;
public SurfaceViewDemo(Context context) {
super(context);
initView();
}
public SurfaceViewDemo(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView();
}
private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
setKeepScreenOn(true);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsDraw = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsDraw = false;
}
//runnable 的run 方法中,我们可以执行绘制的操作
@Override
public void run() {
while (mIsDraw) {
draw();
}
}
private void draw() {
mCanvas = mHolder.lockCanvas();
//draw something
mHolder.unlockCanvasAndPost(mCanvas);
}
}
下面是一些 surfaceView 的实例源码的地址:https://github.com/MoveToNext/SurfaceViewDemo