转载请注明出处:王亟亟的大牛之路
近期两天都没有写文章,一方面是自己在看书。一方面不知道写什么,本来昨天想写Glide或者RxAndroid的东西结果公司的“狗屎”网怎么都刷不好Gradle我也是无语了(翻墙也没用)。准备今天背着笔记本 回家搞。真是服了。。
抱怨的话不说了,来看下这一篇要讲的主角 SurfaceView,关于SurfaceView的文章事实上在别的一些网站上也有,由于我之前没写过,所以也就一直没整这部分的内容(别人写的好坏反正找好的点自己吸收吧,嘿嘿)
问题:SurfaceView是什么?
View类的子类
public class SurfaceView extends View
surfaceView是在一个新起的单独线程中能够又一次绘制画面而View必须在UI的主线程中更新画面。
这点非常重要。那我们能够在哪使用它?那些一直在刷的。还会耗性能的一些UI内容我们能够让他去画。毕竟不在主线程(想想渐变这类的东西)
再例举一些使用场景。假设我要画一个视图他和用户有交互。那么用View还是SurfaceView?
像这种情况就比較推荐用View由于要有Touch事件,用View更合适。而0交互的那些场景用用SurfaceView对性能会有一定的帮助,接下来用样例来详细描写叙述怎样用SurfaceView。
先上效果图
效果非常easy就是在一个Activity里设置了个白色背景,然后写了个“你好”。
来看下代码(一些知识点在标注里说明)
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
/**
* Created by jiajiewang on 16/3/22.
*/
public class CustomView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener {
private Context context;
private SurfaceHolder surfaceHolder;
private CustomThread customThread;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setKeepScreenOn(true);
this.setFocusable(true);
//用于触摸事件
this.setLongClickable(true);
this.context = context;
//获取对象实例
surfaceHolder = this.getHolder();
// 给SurfaceView加入回调
surfaceHolder.addCallback(this);
//创建工作线程
customThread = new CustomThread(surfaceHolder);
}
//创建的时候调用
@Override
public void surfaceCreated(SurfaceHolder holder) {
customThread.canRun = true;
//工作线程開始工作
customThread.start();
Log.d("-->surfaceCreated", "surfaceCreated");
}
//发生改变的时候调用
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d("-->surfaceChanged", "surfaceChanged");
}
//销毁时的时候调用
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
customThread.canRun = false;
Log.d("-->surfaceDestroyed", "surfaceDestroyed");
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d("MotionEvent", "ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.d("MotionEvent", "ACTION_UP");
break;
case MotionEvent.ACTION_MOVE:
Log.d("MotionEvent", "ACTION_MOVE");
break;
}
return super.onTouchEvent(event);
}
}
//工作线程
class CustomThread extends Thread {
private SurfaceHolder surfaceHolder;
public boolean canRun;
public CustomThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
canRun = true;
}
@Override
public void run() {
while (canRun) {
Canvas canvas = null;
//线程同步
synchronized (surfaceHolder) {
//创建画笔
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setTextSize(200);
// 锁定画布(想一下,相似Bitmap的效果)
canvas = surfaceHolder.lockCanvas();
//画背景
canvas.drawColor(Color.WHITE);
//画字
canvas.drawText("妈蛋", 100, 300, paint);
}
if (canvas != null) {
// 结束锁定
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
流程:
这是一个自己定义的SurfaceView并实现了SurfaceHolder.Callback
在这个自己定义SurfaceView被创建的时候去开启工作线程去做了该做的事。MainActivity没做不论什么事也就是 载入一下,还是在XML里引入的。
<sample.wjj.surfaceviewdemo.CustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
那我们来看下 SurfaceView一些比較重要的(经常使用的)方法。
getHolder() 获取SurfaceHolder对象,Surface 就在SurfaceHolder对象内
Canvas lockCanvas()或则Canvas lockCanvas(Rect dirty) 获取Canvas对象
unlockCanvasAndPost(Canvas canvas) 函数会释放该锁,用于操作UI
在调用lockCanvas函数获取Canvas后,SurfaceView会获取Surface的一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁,这里的同步机制保证在Surface绘制过程中不会被改变(被摧毁、改动)。
再说一下绘制的类型(更好的运用性能)
SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface
SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface
SURFACE_TYPE_GPU:适用于GPU加速的Surface
SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包括原生数据,Surface用到的数据由其它对象提供。在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据。这样图像预览会比較流畅。假设设置这种类型则就不能调用lockCanvas来获取Canvas对象了。
由于没有什么其它第三方资源所以就不存源代码了。
假设在学习的过程中有什么问题或者项目中有什么问题须要找人探讨的能够扫下面微信和我沟通(私人微信都不是什么平台的会相对回的比較快,骚扰的别来,坏人烂JJ!!)