• Android修行手册 - TextureView和SurfaceView说明


    往期文章分享

    本文约4.8千字,新手阅读需要8分钟,复习需要3分钟收藏随时查阅不再迷路

    👉关于作者

    众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣 !!!
    专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
    有什么需要欢迎私我,交流群让学习不再孤单

    在这里插入图片描述

    👉前提

    这是小空坚持写的Android新手向系列,欢迎品尝。

    大佬(√)

    新手(√√√)

    👉实践过程

    敲黑板了,敲黑板了,这节是很大的环节,涉及知识很多,建议收藏。

    如果你想要显示实时视频流(也就是在线视频)或任何内容流(如OpenGL 场景),则可以使用 Android 提供的 TextureView 来实现该需求。

    首先,我们需要先熟悉三个概念:SurfaceView, TextureView, SurfaceTexture

    😜SurfaceView

    从设计之初,该控件就存在了,她继承自View,但又与普通View不同,那就是拥有自己的Surface

    我们知道Android中页面会组成View树形结构,只有在顶层的DecorView才是可见的,相反SurfaceView她的工作方式是创建一个区别于应用窗口的新窗口(拥有自己的Layer,是独立的View),,与宿主窗口分离不受其控制,这拥有明显的好处就是可以在不同的线程中处理业务(有时你发现程序命名bug崩溃了但是还在显示就是因为这个原因)。效率很高,尤其是游戏方面渲染方面承担重任。

    image.png
    所以总结一句话就是,她与宿主窗口分离,有独立的上下文context,因此可以在单独线程中处理业务,不受View的属性控制,无法进行平移缩放等转换,不能放到ViewGroup中。

    SurfaceView的核心在于提供了两个线程:UI线程和渲染线程,这两个线程通过“双缓冲”机制来达到高效的界面刷新效果。可以通俗的这么理解:不需要画布,直接在窗口上进行绘图叫做无缓冲绘图。使用一个画布,将所有内容都先画到画布上,然后在整体绘制到窗口上,可以称为单缓冲绘图,那个画布就是一个缓冲区。用了两个画布,一个进行临时的绘图,一个进行最终的绘图,这样就叫做双缓冲。这种机制可以使画面更加流畅的运行。

    😜GLSurfaceView

    继承自SurfaceView,她实现了SurfaceHolder.Callback2接口,既然是继承的那么SurfaceView的全部特性她都有,不仅如此,还有view所有的功能和属性,特别是处理事件的能力,它主要是在SurfaceView的基础上它加入了EGL的管理,并自带了一个GLThread绘制线程(EGLContext创建GL环境所在线程即为GL线程),绘制的工作直接通过OpenGL在绘制线程进行,且不会阻塞主线程,然后将绘制出的结果输出到SurfaceView所提供的Surface上,因此这使得GLSurfaceView也拥有了OpenGlES所提供的图形处理能力,还有个Render接口来支持用户自定义渲染器,通过该接口,使Render的操作行为变得非常灵活,只需要将实现了渲染函数的Renderer的实现类设置给GLSurfaceView即可。

    区别于View的Skia渲染方式,GLSurfaceView的渲染器Renderer使用opengl绘制引擎进行渲染。因此具有GPU加速的特点,GLSurfaceView的效率是SurfaceView的30倍以上,SurfaceView使用画布进行绘制,GLSurfaceView利用GPU加速提高了绘制效率。

    😜SurfaceTexture

    随着时间的推移以及需求的多样性,单纯的SurfaceView已经不满足要求了,所以增加了GLSurfaceView和SurfaceTexture。

    和SurfaceView不同的是,它对图像流的处理并不直接显示,而是转为GL外部纹理,因此可用于图像流数据的二次处理(如Camera滤镜,桌面特效等)。比如Camera的预览数据,变成纹理后可以交给GLSurfaceView直接显示,也可以通过SurfaceTexture交给TextureView作为View heirachy中的一个硬件加速层来显示。

    😜TextureView

    好家伙,随着Android系统进一步发展,人们的要求越来越“变态”,再次增加了TextureView的概念。与SurfaceView相比,TextureView并没有重新创建一个新的单独的Surface用来绘制操作。

    TextureView继承自View,她可以将内容流直接投射到普通View中,可以用于实现Live preview等功能。和SurfaceView不同的是,它不会在Window Mananger Services中单独创建窗口,就像是一般的View一样作为View hierachy中的一份子,因此与其它的View一样在View hierachy中管理与绘制。,所以可以和其它普通View一样可以进行移动,旋转,缩放,动画等变化。它显示的内容流数据可以来自App进程或是远端进程。但需要特别注意的是TextureView必须在硬件加速的窗口中(如果关闭硬件加速,GLES被禁用,TextureView就不能做任何事情),并且消费的内存要比SurfaceView多,并且伴有一定的延迟。

    至于卡顿和抖动的更深层剖析,可参考大佬文章:https://zhuanlan.zhihu.com/p/147322501

    SurfaceView是通过SurfaceHolder.addCallback方法在子线程中更新UI,TextureView则可以通过TextureView.setSurfaceTextureListener在子线程中更新UI。

    对于一些类似于需要不断告诉更新画布的游戏来说,SurfaceView绝对是很不错的选择。但是比如视频播放或相机的开发,TextureView则更加适合。

    最后,总结下这几者的区别和联系。

    • 简单地说:SurfaceView直接输出的,拥有自己独立Surface的View, 它的渲染可以放在单独线程而不是主线程中, 其缺点是不能做变形和动画。
    • SurfaceTexture可以用在非直接输出的内容流上,这样就提供了可以进行二次处理的机会。也同样带来了隐患,这样会有若干帧的延迟。同时,由于它本身管理BufferQueue,因此内存消耗也会稍微大一些。
    • TextureView是一个可以把内容流作为外部纹理输出的, 她本身必须是一个硬件加速层。由于失效(invalidation)和缓冲的特性,TextureView增加了额外1~3帧的延迟显示画面更新。
    • 事实上TextureView本身也包含了SurfaceTexture, 它与SurfaceView+SurfaceTexture组合相比可以完成类似的功能(即把内容流上的图像转成纹理,然后输出), 区别在于TextureView是在View hierachy中做绘制,因此一般它是在主线程上做的(在Android 5.0引入渲染线程后,它是在渲染线程中做的)。而SurfaceView+SurfaceTexture在单独的Surface上做绘制,可以是用户提供的线程,而不是系统的主线程或是渲染线程。
    • 在Android 7.0上系统 Surfaceview 的性能比 TextureView 更有优势,支持对象的内容位置和包含的应用内容同步更新,平移、缩放不会产生黑边。在7.0以下系统如果使用场景有动画效果,可以选择性使用TextureView。
    • TextureView比SurfaceView使用更多的内存。

    👉其他

    📢作者:小空和小芝中的小空
    📢转载说明-务必注明来源:https://zhima.blog.csdn.net/
    📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

    温馨提示点击下方卡片获取更多意想不到的资源。
    空名先生

  • 相关阅读:
    Flink 的集群资源管理
    如何做口碑营销?企业实施网络口碑营销的技巧
    计算机毕业设计django基于python研究生备考互助系统
    高斯消元法
    vue3.0项目实战系列文章 - 菜单的实现及组件封装
    离线数据仓库建设
    (附源码)springboot超市仓库管理系统 毕业设计164555
    FlinkSQL 整合 Hive-- flink-1.13.6
    瀑布模型的软件开发有三个特点?软件生命周期的顺序性
    重写Object类的方法
  • 原文地址:https://blog.csdn.net/qq_27489007/article/details/125460658