Android修行手册 - TextureView和SurfaceView说明

举报
芝麻粒儿 发表于 2022/06/26 15:09:27 2022/06/26
【摘要】 👉关于作者众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)欢迎关注公众号【空名先生】获取更多资源和交流! 👉前提这是小空坚持写的Android新手向系列,欢迎...

👉关于作者

众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!

专注于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使用更多的内存。

📢作者:小空和小芝中的小空

📢转载说明-务必注明来源:芝麻粒儿 的个人主页 - 专栏 - 掘金 (juejin.cn)

📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。