您的位置:首页 > 其它

View之孪生兄弟 ----- SurfaceView

2016-03-22 23:46 357 查看
1、SurfaceView与View的区别

Android系统提供了View进行绘图处理,View可以满足大部分的绘图需求,但在某些时候,却也有些心有余而力不足,特别是在进行一些开发的时候。我们知道,View通过刷新来重绘视图,Android系统通过发出VSYNC信号来进行屏幕的重绘,刷新的间隔时间为16ms。如果在16ms内View完成了你所需要执行的所有操作,那么用户在视觉上,就不会产生卡顿的感觉;而如果执行的操作逻辑太多,特别是需要频繁刷新的界面上,例如游戏界面,那么就会不断阻塞主线程,从而导致画面卡顿。很多时候,在自定义View的Log中经常会看见如下所示的警告。

“Skipped 47 frames! The application may be doing too much work on its main thread”

这些警告的产生,很多情况下就是因为在绘制过程中,处理逻辑太多造成的。

为了避免这一问题的产生,Android系统提供了SurfaceView组件来解决这个问题。SurfaceView可以说是View的孪生兄弟,但它与View还是有所不同的,她们的区别主要体现在以下几点。

1,View主要是用于主动更新的情况下 ,而Surface主要使用与被动更新,例如频繁地刷新。

2,View在主线程对画面进行刷新,而SurfaceView通常会通过一个子线程来进行页面的刷新。

3,View在绘图时没有使用双缓冲机制,而SurfaceView在底层实现机制中就已经实现了双缓冲机制。

总而言之,如果你的自定义View需要频繁刷新,或者刷新时数据处理量比较大,那么你就可以考虑使用SurfaceView来取代View了。

2.SurfaceView的使用

这里继承SurfaceView自定义一个画板(待验证):

package com.test.main;
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.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback,Runnable {
//SurfaceHolder
private SurfaceHolder mHolder;
private Canvas mCanvas;
private boolean mIsDrawing;
private Paint mPaint;
private Path mPath;

public SurfaceViewTemplate(Context context) {
super(context);
initView();
}
public SurfaceViewTemplate(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}

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

private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(3);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);

mPath = new Path();
}

@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 boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_CANCEL) {
return false;
}
float touchX = event.getX();
float touchY = event.getY();
// 点击时
if (action == MotionEvent.ACTION_DOWN) {
mPath.moveTo(touchX,touchY);
}
// 拖动时
if (action == MotionEvent.ACTION_MOVE) {
mPath.lineTo(touchX,touchY);
}
// 抬起时
if (action == MotionEvent.ACTION_UP) {

}
return super.onTouchEvent(event);
}

/**
* 通过判断draw()方法所使用的逻辑时长来确定sleep的时长,
* 这里100ms是一个大致的经验值,这个值得取值一般在50ms到100ms左右。
*/

@Override
public void run() {
long start = System.currentTimeMillis();
while (mIsDrawing){
draw();
}
long end = System.currentTimeMillis();
if(end - start <100){
try{
Thread.sleep(100-(end-start));
}catch (InterruptedException e){
e.printStackTrace();
}
}
}

private void draw() {
while (mIsDrawing) {
try {
synchronized (mHolder) {
mCanvas = mHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mCanvas.drawPath(mPath,mPaint);

}
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (mCanvas != null) {
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: