目录

SurfaceView 和View 的比较大的区别

双缓冲机制

SurfaceView 的简单使用

使用SurfaceView背景问题


网上的文章很齐全了,我根据看的文章写(粘贴)了一点小小的总结,当然,英语比较好的直接看官网的描述是最好的了。

SurfaceView 和View 的比较大的区别

1.View的绘图效率不高,主要用于动画变化较少的程序,SurfaceView 绘图效率较高,我们播放视频,绘制变化较大的动画,都可以使用SurfaceView。

2.View的刷新是要在主线程进行的,而主线程还承担着界面响应的任务,SurfaceView 则可以在子线程中进行刷新操作。

3.SurfaceView拥有独立的Surface,即它不与其宿主窗口共享同一个Surface。一般来说,每一个窗口在SurfaceFlinger服务中都对应有一个Layer,用来描述它的绘图表面。对于那些具有SurfaceView的窗口来说,每一个SurfaceView在SurfaceFlinger服务中还对应有一个独立的Layer或者LayerBuffer,用来单独描述它的绘图表面,以区别于它的宿主窗口的绘图表面。

(https://www.jianshu.com/p/56da8a2f377a)想要了解的朋友可以仔细阅读以下这系列的文章

4.SurfaceView使用双缓冲机制,播放视频时画面更流畅。

双缓冲机制

在运用时可以理解为:SurfaceView在更新视图时用到了两张 Canvas,一张 frontCanvas 和一张 backCanvas ,每次实际显示的是 frontCanvas ,backCanvas 存储的是上一次更改前的视图。当你在播放这一帧的时候,它已经提前帮你加载好后面一帧了,所以播放起视频很流畅。
当使用lockCanvas()获取画布时,得到的实际上是backCanvas 而不是正在显示的 frontCanvas ,之后你在获取到的 backCanvas 上绘制新视图,再 unlockCanvasAndPost(canvas)此视图,那么上传的这张 canvas 将替换原来的 frontCanvas 作为新的frontCanvas ,原来的 frontCanvas 将切换到后台作为 backCanvas 。例如,如果你已经先后两次绘制了视图A和B,那么你再调用 lockCanvas()获取视图,获得的将是A而不是正在显示的B,之后你将重绘的 A 视图上传,那么 A 将取代 B 作为新的 frontCanvas 显示在SurfaceView 上,原来的B则转换为backCanvas。相当与多个线程,交替解析和渲染每一帧视频数据。

SurfaceView 的简单使用

创建MySurfaceView 继承 SurfaceView 实现 SurfaceHolder.Callback 回调 ,以及最好实现 Runnable 接口

public class MySufaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    public MySufaceView(Context context) {
        super(context);
    }

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

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

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    @Override
    public void run() {

    }
}

初始化Holder

创建init() 方法,在构造函数里面调用该方法来注册回调。

public void init(){
        mSurfaceHolder = this.getHolder();
        // 注册回调方法
        mSurfaceHolder.addCallback(this);
         //设置背景透明
        getHolder().setFormat(PixelFormat.TRANSLUCENT);
    }

如果要在SurfaceView 中进行耗时操作,最好在surfaceCreated() 方法中创建一个新的线程 指定为当前。

@Override
    public void surfaceCreated(SurfaceHolder holder)
    {
        LogUtils.i(TAG,"surfaceCreated : view创建");
        // 创建surfaceView时启动线程,如果有使用到线程池,也可以用线程池的线程
        new Thread(this).start();
    }

新线程中的操作

在run()方法中,我们可以进行自己的绘制工作了。

//isRun 标记位
        while (isRun)
        {
            synchronized (this) {
                // 锁定画布
                mCanvas = mSurfaceHolder.lockCanvas();
                try {
                    if (mSurfaceHolder != null && mCanvas != null) {
                         //......dosomething

                    }
                }catch (Exception e) {
                    e.printStackTrace();
                }finally{
                    //绘制结束后
                    // 将画布解锁
                    mSurfaceHolder.unlockCanvasAndPost(mCanvas);
                }
            }
        }

使用SurfaceView背景问题

1.如果希望你的surfaceview 在最顶端,并且会遮挡一切view 

   setZOrderOnTop(true) ;

2.如果你希望在最顶端,并且让背景透明化,那么只要加上以下代码,即可设置为顶端且透明。

  setZOrderOnTop(true) ;

getHolder().setFormat(PixelFormat.TRANSPARENT);

3.如果你希望你的surfaceview 仅仅是让他的背景透明,但是却不透底,(所谓的透底则是因为主题设置了windowIsTranslucent的缘故,直接挖空了布局显示了最底层的手机桌面。)使用以下方式即可:

  getHolder().setFormat(PixelFormat.TRANSPARENT);//初始化的时候调用。

然后在surfaceCreated 方法中,添加自己想要的背景。

mCanvas = mSurfaceHolder.lockCanvas();
if (mCanvas!=null){
    mCanvas.drawColor(getResources().getColor(设置自己想设置的颜色));
}
mSurfaceHolder.unlockCanvasAndPost(mCanvas);

这里需要注意,如果你调用了mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

那么每次都会清除掉背景,你必须重新调用绘制背景的代码。

 

4.如果在surfaceView上绘制surfaceView ,最好使用外层布局包裹surfaceview 的方式。必须在layout.addView之后使用,必须动态调用。

layout.addView(surfaceView);
   surfaceView.setZOrderMediaOverlay(true);

最后:我是看了如下作者的文章:

这两位也是简单讲述了一下 

https://www.jianshu.com/p/a2a235bee59e 

https://www.jianshu.com/p/90a75b9b7115  

这里写了suface 的创建过程

https://www.jianshu.com/p/56da8a2f377a