我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SurfaceView 与 TextureView 详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SurfaceView 与 TextureView 详解

前言

播放视频或者渲染其他的动画的时候,有两个 View 组件可供选择,SurfaceView 和 TextureView,GLSurfaceView 是 SurfaceView 的子类,在 SurfaceView 基础上封装了 EGL 环境管理以及 Render 线程,专用于 3D 游戏开发的视图,这里归类到 SurfaceView 中。在介绍 SurfaceView 与 TextureView 之前,需要先介绍下 Surface。

1 Surface

Surface 就是“表面”的意思,可以简单理解为内存中的一段绘图缓冲区。在 SDK 的文档中,对 Surface 的描述是这样的:“Handle onto a raw buffer that is being managed by the screen compositor”,意思是“由屏幕显示内容合成器(screen compositor)所管理的原生缓冲器的句柄”, 这句话包括下面两个意思:

  • 通过 Surface(因为 Surface 是句柄)就可以获得原生缓冲器以及其中的内容。就像在C语言中,可以通过一个文件的句柄,就可以获得文件的内容一样;
  • 原生缓冲器(rawbuffer)是用于保存当前窗口的像素数据的。

简单的说 Surface 对应了一块屏幕缓冲区,每个 Window 对应一个 Surface,任何 View 都是画在 Surface 上的,传统的 view 共享一块屏幕缓冲区,所有的绘制必须在 UI 线程中进行。我们不能直接操作 Surface 实例,要通过 SurfaceHolder,在 SurfaceView 中可以通过 getHolder() 方法获取到 SurfaceHolder 实例。
Surface 是一个用来画图形的地方,但是我们知道画图都是在一个 Canvas 对象上面进行的,Surface 中的 Canvas 成员,是专门用于提供画图的地方,就像黑板一样,其中的原始缓冲区是用来保存数据的地方。
Surface 本身的作用类似一个句柄,得到了这个句柄就可以得到其中的Canvas、原始缓冲区以及其他方面的内容,所以简单的说 Surface 是用来管理数据的(句柄)。
说完 surface 就可以说 SurfaceView 了。

2 SurfaceView

2.1 SurfaceView 简介

简单的说 SurfaceView 就是一个有 Surface 的 View,SurfaceView 控制这个 Surface 的格式和尺寸以及绘制位置。传统 View 及其派生类的更新只能在 UI 线程,然而 UI 线程还同时处理其他交互逻辑,这就无法保证 view 更新的速度和帧率了,而 SurfaceView 可以用独立的线程来进行绘制。因此可以提供更高的帧率,例如游戏,摄像头取景等场景就比较适合用 SurfaceView 来实现。
SurfaceView 的核心在于提供了两个线程:UI线程和渲染线程,两个线程通过“双缓冲”机制来达到高效的界面刷新效果。
不用画布,直接在窗口上进行绘图叫做无缓冲绘图。用了一个画布,将所有内容都先画到画布上,在整体绘制到窗口上,就该叫做单缓冲绘图,那个画布就是一个缓冲区。用了两个画布,一个进行临时的绘图,一个进行最终的绘图,这样就叫做双缓冲。
而这个双缓冲可以理解为,SurfaceView 在更新视图时用到了两张 Canvas:

  • frontCanvas:实际显示的canvas。
  • backCanvas:存储的是上一次更改前的canvas。

当使用 lockCanvas() 获取画布时,得到的实际上是 backCanvas 而不是正在显示的 frontCanvas,之后你在获取到的 backCanvas 上绘制新视图,再 unlockCanvasAndPost(canvas)此视图,那么上传的这张 canvas 将替换原来的 frontCanvas 作为新的 frontCanvas,原来的 frontCanvas 将切换到后台作为 backCanvas。
双缓冲机制

2.2 SurfaceView 实现机制

SurfaceView 继承自 View,所以它也是一个 View。但是这个 View 和普通的 View 有点不同。SurfaceView 有自己的 Surface,在 Android 中,一个 View 有自己的 Surface,在 WMS 中中就有对应的 WindowState,对应在 SurfaceFlinger 中就有 Layer。
SurfaceView 实现机制
一般的 Activity 包含的多个 View 会组成 View hierachy 的树形结构,只有最顶层的 DectorView 才是对 WMS 可见的,这个 DecorView 在 WMS 中有一个对应的 WindowState,相应的,在 SurfaceFlinger 中有对应的 Layer。而 SurfaceView 正因为它有自己的 Surface,有自己的 Window,它在 WMS 中有对应的 WindowState,在 SurfaceFlinger 中有 Layer。
虽然在 App 端它仍在 View hierachy 中,但在 Server 端(WMS 和 SurfaceFlinger)中,它与宿主窗口是分离的。这样的好处是对这个 Surface 的渲染可以放到单独的线程中去做,渲染时可以有自己的 GL context。这对于一些游戏、视频等性能相关的应用非常有益,因为它不会影响主线程对事件的响应。
但是这也有缺点,因为这个 Surface 不在 View hierachy 中,它的显示也不受 View 的属性控制,所以不能进行平移、缩放等动画,它也不能放在其它 ViewGroup 中,SurfaceView 不能嵌套使用,而且不能使用某些 View 的特性,例如 View.setAlpha()。
从 Android7.0 开始,SurfaceView 的窗口位置与其他 View 渲染同步更新。这意味着在屏幕上平移和缩放 SurfaceView 不会导致渲染失真。

3 TextureView

因为上面所说的 SurfaceView 不在主窗口中,它没法做动画没法使用一些 View 的特性方法,所以在 Android 4.0中引入了 TextureView,它是一个结合了 View 和 SurfaceTexture 的 View 对象
TextureView 是一个可以把内容流作为外部纹理输出在上面的 View,和 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。
SurfaceTexture 可以用作非直接输出的内容流,这样就提供二次处理的机会。与 SurfaceView 直接输出相比,这样会有若干帧的延迟。同时,由于它本身管理 BufferQueue,因此内存消耗也会稍微大一些。

4 SurfaceTexture

SurfaceTexture 是 Surface 和 OpenGL ES(GLES) 纹理的组合。SurfaceTexture 用于提供输出到 GLES 纹理的 Surface。
SurfaceTexture 是从 Android 3.0(API level 11)开始加入,与 SurfaceView 不同的是,它对图像流的处理并不直接显示,而是转为 GL 外部纹理,因此用于图像流数据的二次处理
比如 Camera 的预览数据,变成纹理后可以交给 GLSurfaceView 直接显示,也可以通过 SurfaceTexture 交给TextureView 作为 View heirachy 中的一个硬件加速层来显示。
首先,SurfaceTexture 从图像流 (来自 Camera 预览、视频解码、GL 绘制场景等)中获得帧数据,当调用updateTexImage()时,根据内容流中最近的图像更新 SurfaceTexture 对应的 GL 纹理对象。
SurfaceTexture 包含一个应用是其使用方的 BufferQueue。当生产方将新的缓冲区排入队列时,onFrameAvailable() 回调会通知应用。然后,应用调用 updateTexImage(),这会释放先前占有的缓冲区,从队列中获取新缓冲区并执行 EGL 调用,从而使 GLES 可将此缓冲区作为外部纹理使用。

5 SurfaceView 与 TextureView 的对比

项目SurfaceViewTextureView
内存
耗电
绘制及时1-3帧延迟
动画和截图不支持支持

从性能和安全性角度出发,优先选 SurfaceView,TextureView 是一个不得已的选择

  • 在 Android 7.0 上系统 Surfaceview 的性能比 TextureView 更有优势,支持对象的内容位置和包含的应用内容同步更新,平移、缩放不会产生黑边。 在7.0以下系统如果使用场景有动画效果,可以选择性使用TextureView
  • 由于失效(invalidation)和缓冲的特性,TextureView 增加了额外1~3帧的延迟显示画面更新
  • TextureView 总是使用 GL 合成,而 SurfaceView 可以使用硬件 overlay 后端,可以占用更少的内存。
  • TextureView 的内部缓冲队列导致比 SurfaceView 使用更多的内存。
  • SurfaceView 内部自己持有 Surface,Surface 创建、销毁、大小改变时系统来处理的,通过 SurfaceHolder 的 callback 回调通知。
  • 当画布创建好时,可以将 surface 绑定到 MediaPlayer 中。SurfaceView 如果为用户可见的时候,创建 SurfaceView 的 SurfaceHolder 用于显示视频流解析的帧图片,如果发现 SurfaceView 变为用户不可见的时候,则立即销毁 SurfaceView 的 SurfaceHolder,以达到节约系统资源的目的。

来源地址:https://blog.csdn.net/hello_1995/article/details/127410659

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SurfaceView 与 TextureView 详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android View类与SurfaceView类详解

Android游戏开发中主要的类除了控制类就是显示类,比较重要也很复杂的就是显示和游戏逻辑的处理。在J2ME中可以通过Display和Canvas来实现显示,而Android中处理显示的是View类。下面为大家简单介绍and
2022-06-06

AndroidSurfaceView与TextureView使用方法详细讲解

SurfaceView和TextureView都继承View,与普通的View不同的是,它俩可以在独立线程中绘制渲染,性能更高,所以常被应用在对绘制速率要求比较高的场景,比如相机预览,视频播放等等
2022-11-13

Android 自定义SurfaceView详解

本文简单讨论以后Android游戏引擎模板的架构问题。在Android游戏开发教程之二:View类与SurfaceView类中我们已经谈到,SurfaceView类是有很多优势的,所以在Android游戏开发中还是选择Surf
2022-06-06

Android编程之SurfaceView实例详解

本文实例讲述了Android编程之SurfaceView用法。分享给大家供大家参考,具体如下: 关于surfaceView相关知识: View和SurfaceView主要区别: 1. View只能在UI线程中刷新,而SurfaceView可
2022-06-06

Android编程之SurfaceView学习示例详解

本文实例讲述了Android编程之SurfaceView学习示例。分享给大家供大家参考,具体如下: SurfaceView是View的子类,使用的方式与任何View所派生的类都是完全相同的,可以像其他View那样应用动画,并把它们放到布局中
2022-06-06

Android仿微信清理内存图表动画(解决surfaceView屏幕闪烁问题)demo实例详解

最近接了一个项目其中有功能要实现一个清理内存,要求和微信的效果一样。于是想到用surfaceView而不是继承view。下面小编给大家解析下实现思路。 surfaceView是为了解决频繁绘制动画产生了闪烁,而采用了双缓冲机制,即A、B两个
2022-06-06

ListPreference详解与使用

ListPreference是Android中的一个Preference子类,用于显示一个可选择的列表,并且可以保存用户所选择的值。在使用ListPreference时,需要先定义一个XML文件,其中包含了列表的显示名称和对应的值。下面是一
2023-09-14

java 中Comparable与Comparator详解与比较

java 中Comparable与Comparator详解今天查看TreeMap的源码,发现其键必须是实现Comparable或者Comparator的接口时产生了一些兴趣,比如在TreeMap中的put方法分别对Comparable和Co
2023-05-31

python ast 详解与用法

目录 基本概念节点类型ast.Assignast.Nameast.Constantast.Callast.Attribute 结点的遍历ast源码示例 结点的修改示例 参考链接 基本概念 在 python 中,我们可
2023-08-24

详解spring与shiro集成

Shiro的组件都是JavaBean/POJO式的组件,所以非常容易使用Spring进行组件管理,可以非常方便的从ini配置迁移到Spring进行管理,且支持JavaSE应用及Web应用的集成。在示例之前,需要导入shiro-spring及
2023-05-31

详解nginx的root与alias

文章目录 1. 结论2. 详解root2.1 基本用法2.2 location的最左匹配原则2.3 index2.4 nginx location解析url工作流程2.5 末尾'/' 3. 详解alias3.1 基本用法 4
2023-08-19

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录