SurfaceView和TextureView 基础概念

 

目录

1.surface定义:

2.surfaceView 是什么?

3.surfaceView的双缓存机制

4.surfaceView ,Surface,SurfaceHolder 关系图

5.SurfaceView 使用小实例: 绘制正选曲线代码如下

6.SurfaceView 总结:

7.TextureView是什么

7.1TextureView优点及缺点

8.textureView 和 SurfaceView使用总结:


学习surfaceView之前先了解以下surface的一些知识

1.surface定义:

Surfaces是用来处理屏幕显示内容合成器所管理的原始缓存区的工具。android在设计时基于共享内存设计了一套Surface机制,在应用程序这端,Surface可以简单的理解为绘制时用的画布,在程序中可以抽象为一块内存,应用程序绘制前通过WMS先在SurfaceFlinger申请一个Surface,然后就可以随意的绘制,绘制完之后,通知SurfaceFlinger将该Surface合成输出即可。

 

2.surfaceView 是什么?

它继承自类View,因此它本质上是一个View。但与普通View不同的是,它有自己的Surface,在WMS中有对应的WindowState,在SurfaceFlinger中有Layer。

我们知道,一般的Activity包含的多个View会组成View hierachy(view树形结构).只有最顶层的DecorView,也就是根结点视图,才是对WMS可见的(根层是挂在窗体上的)。这个DecorView在WMS中有一个对应的WindowState。相应地,在SurfaceFlinger中对应的Layer。而SurfaceView自带一个Surface,这个Surface在WMS中有自己对应的WindowState,在SurfaceFlinger中也会有自己的Layer。虽然在App端surfaceView它仍在View hierachy中,但在Server端(WMS和SF)中,它与宿主窗口是分离的。这样的好处是对这个Surface的渲染可以放到单独线程去做。这对于一些游戏、视频等性能相关的应用非常有益,因为它不会影响主线程对事件的响应。但它也有缺点,因为这个Surface不在View hierachy中,它的显示也不受View的属性控制,所以不能进行平移,缩放等变换

 

3.surfaceView的双缓存机制

什么是缓冲:在我们的界面中图形都是在画布上绘制出来的,所以这个绘制过程就叫缓冲,而画布也可以称作缓冲区。

无缓冲:不使用画布的情况下直接在窗口上进行绘图就叫做无缓冲绘图。

单缓冲:用了一个画布,将所有的内容先绘制到画布上,再整体绘制到窗口,这个就叫做单缓冲绘图。Android中View的onDraw()方法已经实现了这一层缓冲。onDraw()方法中不是绘制一点显示一点,而是都绘制完后

双缓冲:用了两个画布,一个进行临时的绘图,一个进行最终的绘图,这样的就叫做双缓冲绘图。

   onDraw()方法的Canvas对象是和屏幕关联的,而onDraw()方法是运行在UI线程中的,如果要绘制的图像过于复杂,则有可         能导致应用程序卡顿,甚至ANR。因此我们可以先创建一个临时的Canvas对象,将图像都绘制到这个临时的Canvas对象       中,绘制完成之后再将这个临时Canvas对象中的内容,绘制到要显示onDraw()方法中的canvas对象中。这样的话就相当于是一个拷贝过程,比直接绘制效率要高,可以减少对UI线程的阻塞

 

SurfaceView在更新视图时用到了两张Canvas,一张frontCanvas(显示)和一张backCanvas(存储),每次实际显示的是frontCanvas,backCanvas存储的是上一次更改前的视图。通过使用SurfaceHolder的lockCanvas()获取画布,得到的实际上是backCanvas而不是正在显示的frontCanvas,之后在获取到的backCanvas上绘制新视图,再通过SurfaceHolder的unlockCanvasAndPost(canvas)方法将视图更新到显示的视图上,那么上传的这张canvas将替换原来的frontCanvas作为新的frontCanvas,原来的frontCanvas将切换到后台作为backCanvas。

 

双缓存的优点:比直接绘制效率要高,相当于一个拷贝过程,可以减少对UI线程的阻塞,绘制特别及时没有延迟,可以把要绘制的数据放到子线程操作,提高效率。

 

 

 

 

4.surfaceView ,Surface,SurfaceHolder 关系图

此图展示了一个mvc的架构模式: 这3者之间其实是典型的MVC模式,其中SurfaceView对应的就是View层,SurfaceHolder就是controller接口,而Surface就是对应的Model层,它里面持有Canvas,保存着绘制的数据

调用接口如下图:

 

 

5.SurfaceView 使用小实例: 绘制正选曲线代码如下

package com.study.study.view;
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.SurfaceHolder;
import android.view.SurfaceView;
/***
 * surfaceView的使用;
 */
public class MySurfaceView extends SurfaceView  implements SurfaceHolder.Callback ,Runnable{


    private SurfaceHolder mHolder;
    private Canvas mCanvas;//绘图的画布
    private boolean mIsDrawing;//控制绘画线程的标志位

    public static final int TIME_IN_FRAME = 30;
    private Path mPath;
    private Paint mPaint;
    private int x = 0, y = 0;

    public MySurfaceView(Context context) {
        super(context);
        init();
    }

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

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

    private void init() {
        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(5);
        mPath = new Path();
        //路径起始点(0, 100)
        mPath.moveTo(0, 100);


        //获取创建的surfaceHolder
        mHolder = getHolder();
        //设置回调监听
        mHolder.addCallback(this);
        //设置有焦点
        setFocusable(true);

        setFocusableInTouchMode(true);
        //屏幕常亮;
        this.setKeepScreenOn(true);
    }


    /************以下实现surfaceHolder.callback的接口回调******************/
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
       //表示surfaceView创建成功可用,
        //设置标志位
        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方法的回调开子线程------------------------------------**/
    @Override
    public void run() {
        //在子线程中进行绘画操作

        while (mIsDrawing) {
            //进行绘制
            doDrawSometing();
            x += 1;
            y = (int)(100 * Math.sin(2 * x * Math.PI / 180) + 400);
            //加入新的坐标点
            mPath.lineTo(x, y);
        }
    }

    private void doDrawSometing() {

        synchronized (mHolder) {
            try{
                mCanvas=mHolder.lockCanvas();//获取Canvas对象进行绘制
                //SurfaceView背景
                mCanvas.drawColor(Color.WHITE);
                mCanvas.drawPath(mPath,mPaint);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                if (mCanvas!=null){
                    mHolder.unlockCanvasAndPost(mCanvas);//保证绘制的画布内容提交
                }
            }
        }
    }

}

 

测试结果:

 

6.SurfaceView 总结:

优点:可以在一个独立的线程中进行绘制,不会影响主线程

          使用双缓冲机制,播放视频时画面更流畅 没有延迟现象

缺点:Surface不在View hierachy中,它的显示也不受View的属性控制,所以不能进行平移,缩放等变换,也不能放在其它ViewGroup中。SurfaceView 不能嵌套使用

 

7.TextureView是什么

在4.0(API level 14)中引入,与SurfaceView一样继承View,     它可以将内容流直接投影到View中,它可以将内容流直接投影到View中,可以用于实现Live preview等功能。和SurfaceView不同,它不会在WMS中单独创建窗口,而是作为View hierachy中的一个普通View,因此可以和其它普通View一样进行移动,旋转,缩放,动画等变化。值得注意的是TextureView必须在硬件加速的窗口中。它显示的内容流数据可以来自App进程或是远端进程。TextureView继承自View,它与其它的View一样在View hierachy中管理与绘制。TextureView重载了draw()方法,其中主要SurfaceTexture中收到的图像数据作为纹理更新到对应的HardwareLayer中。SurfaceTexture.OnFrameAvailableListener用于通知TextureView内容流有新图像到来。SurfaceTextureListener接口用于让TextureView的使用者知道SurfaceTexture已准备好,这样就可以把SurfaceTexture交给相应的内容源。Surface为BufferQueue的Producer接口实现类,使生产者可以通过它的软件或硬件渲染接口为SurfaceTexture内部的BufferQueue提供graphic buffer。

 

7.1TextureView优点及缺点

 

优点:支持移动、旋转、缩放等动画,支持截图

缺点:必须在硬件加速的窗口中使用,占用内存比SurfaceView高,

在5.0以前在主线程渲染,5.0以后有单独的渲染线程。

 

8.textureView 和 SurfaceView使用总结:

1、在android 7.0上系统surfaceview的性能比TextureView更有优势,支持对象的内容位置和包含的应用内容同步更新,平移、缩放不会产生黑边。 在7.0以下系统如果使用场景有动画效果,可以选择性使用TextureView

2、由于失效(invalidation)和缓冲的特性,TextureView增加了额外1~3帧的延迟显示画面更新

3、TextureView总是使用GL合成,而SurfaceView可以使用硬件overlay后端,可以占用更少的内存带宽,消耗更少的能量

4、TextureView的内部缓冲队列导致比SurfaceView使用更多的内存

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值