转载:https://blog.youkuaiyun.com/rong_wz/article/details/51956463
转载:https://www.jianshu.com/p/acf574f08efc
转载:https://blog.youkuaiyun.com/android_cmos/article/details/68955134
什么是surface?
我们知道Activity是用了来显示界面的,那么Activity的界面是如何绘制出来的呢?这个肯定和Surface有关,但是博主是新手,具体关联就不清楚,博主自己理解,Surface就像屏幕上的一个画布,canvas是一位画家,paint就是一支笔,view其实就是由一位画家canvas还有一些关于view自身的事件的组成的一个对象,有了canvas,就可以往surface上面作画了,而每一个window对应一个Surface,任何View都是显示在Surface上的,传统的view共享一个surface,但因为view只能在ui线程更新,所以view里面的画手canvas消耗的时间是主线程出的(为什么?因为如果多线程操作ui,就会涉及到同步和锁之类的,这样子效率就不高,所以系统把所有ui操作都在主线程执行,当操作ui时候,如果判断不当前线程不是主线程,直接抛异常),因此,用传统ui做频繁的更新操作,会引起线程的阻塞,从而造成卡顿,严重会出现无响应,所以这个时候,需要surfaceView。
什么是surfaceView?
surfaceView本身继承于view,符合view的所有特性,但是还不够严谨,看下图。
上图是SurfaceView源码,可以知道SurfaceView的创建会新建一个窗口,而这个newMyWindow(this)的this就是指的surfaceView对象本身,从上面知道,surfaceView有自己的window,上面说了,每个window对应一个surface,所以SurfaceView内嵌了一个自己的Surface,所以SurfaceView和传统的view不是共用一个surface,并且和传统的view还有不同的是,view是绘制在suface之上的,但是surfaceView是绘制在surface中,意思就像,一般的view就像在琥珀上面画画,而surfaceView就是琥珀里面的东西,另外,view的绘制用到的画手消耗的时间是在主线程里面出的,但是surfaceview画图,就像琥珀里面的东西,它不用外在的画上去所以不需要消耗主线程的时间,只需要内部的描绘出来,描绘出来的这段时间,可以用子线程来执行,所以surfaceView用来做游戏,录播播放还有一些频繁更新的操作,因此surfaceView你可以理解为只是一个改变surface画布大小和位置的一个view。.
如何surfaceView?
首先SurfaceView也是一个View,它也有自己的生命周期。因为它需要另外一个线程来执行绘制操作,所以我们可以在它生命周期的初始化阶 段开辟一个新线程,然后开始执行绘制,当生命周期的结束阶段我们插入结束绘制线程的操作。这些是由其内部一个SurfaceHolder对象完成的。
SurfaceView它的绘制原理是绘制前先锁定画布(获取画布),然后等都绘制结束以后在对画布进行解锁 ,最后在把画布内容显示到屏幕上。
通常情况下,使用以下步骤来创建一个SurfaceView的模板:
(1)创建SurfaceView
创建自定义的SurfaceView继承自SurfaceView,并实现两个接口:SurfaceHolder.Callback和Runnable.代码如下
public class MySurfaceView extends SurfaceView implements Runnable,SurfaceHolder.Callback{
通过实现这两个接口,就需要在自定义的SurfaceView中实现接口的方法,对于SurfaceHolder.Callback方法,需要实现如下方法,其实就是SurfaceView的生命周期:
@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;
}
对于Runnable接口,需要实现run()方法,
@Override
public void run() {
while (mIsDrawing){
try {
mCanvas = mHolder.lockCanvas();
// draw sth绘制过程
} catch (Exception e) {
} finally {
if (mCanvas != null)
mHolder.unlockCanvasAndPost(mCanvas);//保证每次都将绘图的内容提交
}
}
}
(2)初始化SurfaceView
在自定义的MySurfaceView的构造方法中,需要对SurfaceView进行初始化,包括SurfaceHolder的初始化、画笔的初始化等。在自定义的SurfaceView中,通常需要定义以下三个成员变量:
private SurfaceHolder mHolder;
private Canvas mCanvas;//绘图的画布
private boolean mIsDrawing;//控制绘画线程的标志位
SurfaceHolder,顾名思义,它里面保存了一个对Surface对象的引用,而我们执行绘制方法本质上就是操控Surface。SurfaceHolder因为保存了对Surface的引用,所以使用它来处理Surface的生命周期。(说到底 SurfaceView的生命周期其实就是Surface的生命周期)例如使用 SurfaceHolder来处理生命周期的初始化。
初始化代码如下:
public MySurfaceView(Context context) {
super(context);
initView();
}
private void initView() {
mHolder = getHolder();//获取SurfaceHolder对象
mHolder.addCallback(this);//注册SurfaceHolder的回调方法
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);//保持屏幕常亮
}
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
(2)SurfaceView总体使用
package com.slide.aier.myview;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* Created by aier on 2018/6/23.
*/
public class MySurfaceView extends SurfaceView implements Runnable,SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private Canvas mCanvas;//绘图的画布
private boolean mIsDrawing;//控制绘画线程的标志位
public MySurfaceView(Context context) {
super(context);
initView();
}
private void initView() {
mHolder = getHolder();//获取SurfaceHolder对象
mHolder.addCallback(this);//注册SurfaceHolder的回调方法
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);//保持屏幕常亮
}
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
@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){
try {
mCanvas = mHolder.lockCanvas();
// draw sth绘制过程
} catch (Exception e) {
} finally {
if (mCanvas != null)
mHolder.unlockCanvasAndPost(mCanvas);//保证每次都将绘图的内容提交
}
}
}
}