SurfaceView和TextureView的使用以及区别

一 、 什么时候使用SurfaceView

我们平时学习自定义view的过程中会发现自定义的View可以满足大部分的绘图需求,但是当我们需要绘制的内容多且复杂(或者需要频繁刷新)时,View就有些难堪重任了,这时候就需要使用到android 为我们提供的SurfaceView了

二 、 SurfaceView相对于自定义View的优势

  1. View在主线程更新UI,SurefaceView在子线程更新UI
  2. View更适用于较为简单耗时短的绘图,SurfaceView可以绘制复杂的页面不会因为16ms内未绘制完出现卡顿的情况
  3. SurfaceView更倾向于主动频繁刷新的UI

三 、 SurfaceView的使用

  1. 创建自定义View继承SurfaceView,实现SurfaceHolder.Callback接口
  2. 初始化SurfaceView,设置回调addCallback(this) 和一下窗口属性
  3. 开启创建开启线程,在run()方法中通过mSurfaceHolder.lockCanvas()获取canvas进行绘图,绘制完成后通过unlockCanvasAndPost()方法释放提交画布

下面是示例代码

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback ,Runnable{private SurfaceHolder mSurfaceHolder;private Thread mThread;private boolean isRunning;private Canvas mCanvas;public MySurfaceView(Context context) {this(context,null);}public MySurfaceView(Context context, AttributeSet attrs) {this(context, attrs,-1);}public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView();}private void initView() {mSurfaceHolder = getHolder();//设置回调mSurfaceHolder.addCallback(this);//获取焦点setFocusable(true);setFocusableInTouchMode(true);//保持常亮setKeepScreenOn(true);//设置View位于布局最上层     这个属性搭配下面的设置可以实现背景透明(解决透明后直接展示桌面的BUG)//可以通过windowManager的addView方法添加布局位于surfaceView的上方setZOrderOnTop(true);mSurfaceHolder.setFormat(PixelFormat.TRANSLUCENT);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {mThread = new Thread(this);isRunning = true;mThread.start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {//销毁的时候,关闭线程isRunning = false;}@Overridepublic void run() {while (isRunning) {long start = System.currentTimeMillis();draw();long end = System.currentTimeMillis();if ((end - start) < 50) {//控制绘制间隔SystemClock.sleep(50-(end - start));}}}private void draw(){try {mCanvas = mSurfaceHolder.lockCanvas();if (mCanvas != null) {//背景透明时设置清屏mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//todo 绘图}} catch (Exception e) {} finally {//释放canvas避免内存泄漏mSurfaceHolder.unlockCanvasAndPost(mCanvas);}}
}

使用过程值得注意的地方

  • surfaceView更像是一个独立的window不可以像View一样执行动画,也不受View的属性控制
  • SurfaceView就是在窗口上挖一个洞,它就是显示在这个洞里,其他的View是显示在窗口上,所以View可以显式在 SurfaceView之上,你也可以添加一些层在SurfaceView之上
  • surfaceView采用了双缓冲技术(对双缓冲感兴趣的自行百度),每次的绘制都是覆盖绘制(在上一次的显示基础上进行绘制),如果不想覆盖(例如设置背景透明时绘制的背景图片边缘有阴影效果的情况)可以添加清屏操作,然后再进行绘制
  • surfaceView的绘制间隔最好保持一致,否则可能会出现卡顿现象
  • 使用setZOrderOnTop(true);设置背景透明会导致遮挡其他布局的现象,可以考虑使用windowManager的addView方法添加位于surfaceView上方的布局(或者使用TextureView替换surfaceView)

四 、 TextureView的使用

textureView的使用和surfaceView十分相似,示例代码如下

public class MyTextureView extends TextureView implements Runnable, TextureView.SurfaceTextureListener {private Thread mThread;private boolean isRunning;private Canvas mCanvas;public MyTextureView(Context context) {this(context,null);}public MyTextureView(Context context, AttributeSet attrs) {this(context, attrs,-1);}public MyTextureView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView();}private void initView() {//设置监听setSurfaceTextureListener(this);//获取焦点setFocusable(true);setFocusableInTouchMode(true);//保持常亮setKeepScreenOn(true);//设置背景透明setOpaque(false);}@Overridepublic void run() {while (isRunning) {long start = System.currentTimeMillis();draw();long end = System.currentTimeMillis();if ((end - start) < 50) {//控制绘制间隔SystemClock.sleep(50-(end - start));}}}private void draw(){try {mCanvas = lockCanvas();if (mCanvas != null) {//背景透明时设置清屏mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//todo 绘图}} catch (Exception e) {} finally {if (mCanvas != null) {//释放canvas避免内存泄漏unlockCanvasAndPost(mCanvas);}}}@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {mThread = new Thread(this);isRunning = true;mThread.start();}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {//销毁的时候,关闭线程isRunning = false;return false;}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surface) {}
}

五 、SurfaceView和TextureView和自定义View的区别

  1. SurfaceView和TextureView都是在子线程更新UI
  2. SurfaceView和TextureView都继承自View
  3. SurfaceView不能使用动画,两个SurfaceView不能相互覆盖
  4. TextureView4.0以后才能使用
  5. TextureView只能在开启了硬件加速的Window中使用,消费的内存要比SurfaceView多,并伴随着1-3帧的延迟。
  6. TextureView 需要通过UI Renderer输出。除了性能比较 SurfaceView 会有明显下降外(低端机,高 GPU 负荷场景可能存在 15% 左右的帧率下降),另外因为需要在三个线程之间进行写读同步(包括 CPU 和 GPU 的同步),当同步失调的时候,比较容易出现掉帧或者吞帧导致的卡顿和抖动现象。
  7. SurfaceView的窗口刷新的时候不需要重绘应用程序的窗口而android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者是局部的刷新都会导致整个视图结构全部重绘一次。

SurfaceView和TextureView的使用以及区别相关推荐

  1. Android openGl开发详解(二)——通过SurfaceView,TextureView,GlSurfaceView显示相机预览(附Demo)

    最近公司在做自定义相机这一块,之前使用的是第三方,后来需求变更,第三方不支持添加动态贴纸,所以只能自己扩展.当然网上有很多例子,但是关于添加动态贴纸的例子几乎找不到,反正我是没找到(欲哭无泪).当然, ...

  2. SurfaceView和View最本质的区别

    SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面. 那么在UI的主线程中更新画面 可能会引发问题, ...

  3. SurfaceView 与 TextureView 详解

    前言 播放视频或者渲染其他的动画的时候,有两个 View 组件可供选择,SurfaceView 和 TextureView,GLSurfaceView 是 SurfaceView 的子类,在 Surf ...

  4. 浅谈 SurfaceView、TextureView、GLSurfaceView、SurfaceTexture

    一.SurfaceView SurfaceView 是一个可以在子线程中更新 UI 的 View,且不会影响到主线程.它为自己创建了一个窗口(window),就好像在视图层次(View Hierarc ...

  5. Android SurfaceView、TextureView区别

    SurfaceView是一个有自己独立Surface的View, 它的渲染可以放在单独线程而不是主线程中, 其缺点是不能做变形和动画.继承:MockView SurfaceTexture可以用作非直接 ...

  6. SurfaceView及TextureView区别

    1.SurfaceView是什么 它继承自类View,因此它本质上是一个View.但与普通View不同的是,它有自己的Surface.有自己的Surface,在WMS中有对应的WindowState, ...

  7. SurfaceView,TextureView,SurfaceTexture相关

    首先我们知道View类如果需要更新视图,必须我们主动的去调用invalidate()或者postInvalidate()方法来再走一次onDraw()完成更新.但是呢,Android系统规定屏幕的刷新 ...

  8. Android TextureView 与 SurfaceView用法区别

    SurfaceView和TextureView均继承于android.view.View,与其它View不同的是,两者都能在独立的线程中绘制和渲染,在专用的GPU线程中大大提高渲染的性能. 一.Sur ...

  9. Android显示系统之View与SurfaceView更新屏幕的区别

    /******************************************************************************************** * auth ...

最新文章

  1. python一次性读取整个文件-python – 如何一次读取和附加到文本文件?
  2. IT技术文章示例(附源码)
  3. 为什么linux进程名匹配最多只支持15个字符?
  4. cacti + nagios + npc 整合部署
  5. 1 SD配置-企业结构-定义-定义销售组织
  6. 大佬应该都懂的python语法,看看哪些是你不知道的?
  7. Spring Boot(17)配置文件解析
  8. @property、@staticmethod、@classmethod装饰器
  9. 信号与系统公式笔记(8)——拉普拉斯变换
  10. window10激活
  11. 虚拟文件系统VSF的作用
  12. html表格中如何画单元格中对角线
  13. 缘,如雁渡寒潭,似风吹疏竹
  14. 关联规则:R与SAS的比较
  15. php必应壁纸 分辨率,必应壁纸php获取接口
  16. 解决Gitlab的The remote end hung up unexpectedly错误
  17. centos安装python3.8.1_在CentOS 8上编译安装Python 3.8.1
  18. 数学建模经验谈(四)-参加国赛的几点建议
  19. 三维地图开发平台-支持离线地图开发
  20. Axure 高保真 日期选择器实现 可选任意年/月/日

热门文章

  1. 车脉科技:业内首创“车企体验式营销”
  2. 自制聊天机器人实现与chatgpt或微信好友对话【附代码】
  3. Android OpenGL ES 旋转glRotatef
  4. 程序员看过都说好的资源网站,你值得拥有。
  5. mDNS 原理的简单理解
  6. 运动算法 一范数 二范数 敏感轴
  7. 基于虹软人脸识别,实现超市人脸支付
  8. Python基础五 字典(dic)
  9. vue中绑定style样式的方式
  10. 在python领域有名的培训机构排名出炉