Android中SurfaceView与GLSurfaceView 的关系
SurfaceView 与 GLSurfaceView 的关系
在 Android 开发中,SurfaceView 和 GLSurfaceView 是实现自定义渲染效果的关键组件。它们提供了不同的渲染方式,适用于不同的应用场景。我们将通过以下几个方面详细说明 SurfaceView 和 GLSurfaceView 的特点及实现原理,并结合 GLSurfaceView 的源码进行深入分析。

1. 概述
-
SurfaceView:提供一个独立的绘制表面 (Surface),用于在子线程中渲染图像。它适用于需要高频率更新画面的应用场景,如视频播放、相机预览等。
-
GLSurfaceView:继承自
SurfaceView,封装了 OpenGL 的渲染环境,为应用提供了更简便的 OpenGL 渲染接口。适用于图形密集的应用场景,如 3D 游戏或数据可视化。
2. SurfaceView 的实现与原理
2.1 工作原理
SurfaceView 的核心在于提供了一个独立的 Surface,即在独立于主线程的后台线程上绘制内容。SurfaceView 通过 SurfaceHolder 来管理 Surface 的生命周期,确保绘制与 UI 更新分离,提高渲染效率。
2.2 SurfaceHolder 机制
SurfaceView 使用 SurfaceHolder 管理 Surface 的创建、销毁和变化,主要方法包括:
SurfaceHolder.Callback:监听Surface的生命周期变化。lockCanvas()和unlockCanvasAndPost():锁定画布进行绘制,解锁画布并提交绘制结果。
2.3 示例代码
class MySurfaceView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {init {holder.addCallback(this)}override fun surfaceCreated(holder: SurfaceHolder) {val canvas = holder.lockCanvas()// 在canvas上绘制holder.unlockCanvasAndPost(canvas)}override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {// Surface 改变时调用}override fun surfaceDestroyed(holder: SurfaceHolder) {// Surface 销毁时调用}
}
3. GLSurfaceView 的实现与源码解析
GLSurfaceView 是 SurfaceView 的子类,旨在为 OpenGL 渲染提供支持。GLSurfaceView 封装了 OpenGL 的初始化、渲染线程管理等,简化了开发流程。通过 GLSurfaceView,开发者可以更轻松地将 OpenGL 绘图代码与 Android 的渲染机制结合。
3.1 核心类分析
- GLSurfaceView:提供了
GLSurfaceView.Renderer接口,用于实现自定义的 OpenGL 渲染逻辑。主要方法包括onSurfaceCreated()、onDrawFrame()和onSurfaceChanged()。 - GLThread:负责管理 OpenGL 的渲染线程。
GLThread保持 OpenGL 上下文,确保渲染工作在独立线程中完成,避免阻塞主线程。
3.2 GLSurfaceView 源码分析
在 GLSurfaceView 中,setRenderer() 会启动一个 GLThread 线程,调用开发者自定义的 Renderer 方法。GLThread 使用 OpenGL API 进行绘图,同时将绘制操作与 UI 线程分离。
public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {// 1. 初始化渲染器public void setRenderer(Renderer renderer) {checkRenderThreadState();mRenderer = renderer;mGLThread = new GLThread(mThisWeakRef);mGLThread.start(); // 启动GLThread线程}// 2. GLThread:渲染线程private static class GLThread extends Thread {private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;GLThread(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) {mGLSurfaceViewWeakRef = glSurfaceViewWeakRef;}@Overridepublic void run() {// 渲染主循环while (true) {// 执行 OpenGL 绘制if (glSurfaceView.mRenderer != null) {glSurfaceView.mRenderer.onDrawFrame(gl);}}}}
}
3.3 Renderer 接口方法
onSurfaceCreated():在创建 OpenGL 表面时调用,用于初始化 OpenGL 环境。onSurfaceChanged():当视图大小或形状改变时调用,用于适应新的显示区域。onDrawFrame():在每一帧绘制时调用,实际的绘图逻辑写在此方法中。
class MyGLRenderer : GLSurfaceView.Renderer {override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {// 初始化OpenGL相关资源}override fun onDrawFrame(gl: GL10?) {// 绘制每一帧}override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {// 更新视图大小GLES20.glViewport(0, 0, width, height)}
}

4. SurfaceView 与 GLSurfaceView 的区别
| 特性 | SurfaceView | GLSurfaceView |
|---|---|---|
| 渲染技术 | Canvas | OpenGL |
| 渲染线程 | 可在自定义线程中渲染 | 自动管理 OpenGL 渲染线程 |
| 应用场景 | 视频播放、相机预览 | 3D 游戏、图形密集的应用 |
| 渲染接口 | lockCanvas() 和 unlockCanvasAndPost() | Renderer 接口,提供 onDrawFrame() 等方法 |
5. 总结
SurfaceView 和 GLSurfaceView 是 Android 中用于自定义渲染的重要组件,适用于不同的应用场景。SurfaceView 提供了在独立线程上绘制内容的机制,而 GLSurfaceView 则为 OpenGL 渲染进行了更高层次的封装,使得图形密集型应用的开发更加便捷。
在实际开发中,选择 SurfaceView 还是 GLSurfaceView 主要取决于渲染需求,如果应用需要大量的 3D 图形渲染或频繁更新的图像内容,GLSurfaceView 是更优选择。
参考
http://labs.beatcraft.com/ja/index.php?Android%20%A4%C7%20OpenGL%20ES%20%20%A4%F2%BB%C8%CD%D1%A4%B9%A4%EB
相关文章:
Android中SurfaceView与GLSurfaceView 的关系
SurfaceView 与 GLSurfaceView 的关系 在 Android 开发中,SurfaceView 和 GLSurfaceView 是实现自定义渲染效果的关键组件。它们提供了不同的渲染方式,适用于不同的应用场景。我们将通过以下几个方面详细说明 SurfaceView 和 GLSurfaceView 的特点及实现…...
numpy——数学运算
一、标量——矢量 import numpy as npa 3.14 b np.array([[9, 5], [2, 7]])print(a) print(b)# ---------- 四则运算 ---------- print(a b) # np.add print(a - b) # np.subtract print(a * b) # np.multiply print(a / b) # np.divide 二、矢量——矢量 import nump…...
【工具】Charles对360浏览器抓包抓包
Charles 和 switchy sharp 配合,可以对 Chrome 进行抓包也可以配合对360安全浏览器抓包。 本文以Windows 电脑中的配置为例,介绍如何实现抓包。(Mac中操作基本一致) 1.安装Charles 可根据自己的电脑下载对应的版本:…...
【HarmonyOS】判断应用是否已安装
【HarmonyOS】判断应用是否已安装 前言 在鸿蒙中判断应用是否已安全,只是通过包名是无法判断应用安装与否。在鸿蒙里新增了一种判断应用安装的工具方法,即:canOpenLink。 使用该工具函数的前提是,本应用配置了查询标签querySch…...
Qt Designer客户端安装和插件集(pyqt5和pyside2)
GitHub - PyQt5/QtDesignerPlugins: Qt Designer PluginsQt Designer Plugins. Contribute to PyQt5/QtDesignerPlugins development by creating an account on GitHub.https://github.com/PyQt5/QtDesignerPlugins 一、下载客户端 https://github.com/PyQt5/QtDesigner/rel…...
基于边缘计算的智能门禁系统架构设计分析
案例 阅读以下关于 Web 系统架构设计的叙述,回答问题1至问题3。 【说明】 某公司拟开发一套基于边缘计算的智能门禁系统,用于如园区、新零售、工业现场等存在来访被访业务的场景。来访者在来访前,可以通过线上提前预约的方式将自己的个人信息…...
鸿蒙实现相机拍照及相册选择照片
前言: 1.如果你的应用不是存储类型或者相机拍照类型,你就需要用 kit.CameraKit Api 实现相机拍照和相册选择照片功能,如果你不用这个的话,你使用 picker.PhotoViewPicker ,你就需要申请权限,那你提交应用审…...
「C/C++」C++17 之 std::filesystem::recursive_directory_iterator 目录及子目录迭代器
✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…...
智能EDA小白从0开始 —— DAY30 冉谱微RFIC-GPT
在科技日新月异的今天,电子设计自动化(EDA)行业正以前所未有的速度推动着半导体产业的革新与发展,引领着全球电子产业迈向更加智能化、高效化的未来。作为EDA领域的佼佼者,冉谱公司始终站在技术创新的前沿,…...
Android -- 调用系统相册之图片裁剪保存
前言 最近线上反馈,部分vivo手机更换头像时调用系统相册保存图片失败,经本人测试,确实有问题。 经修复后,贴出这块的代码供小伙伴们参考使用。 功能 更换头像选择图片: 调用系统相机拍照,调用系统图片…...
读《道德经》让人感到心胸气闷?董仲舒篡改
为什么读《道德经》会让人感到心胸气闷?难道是董仲舒篡改所致? 作为世界智慧源头的《老子》,享誉古今中外,是世界历史上最伟大的著作之一。 然而,很多人读《道德经》时会感到心胸气闷,这究竟是为什么呢&am…...
D52【python 接口自动化学习】- python基础之模块与标准库
day52 标准库 学习日期:20241029 学习目标:模块与标准库 -- 67 标准库:Python默认提供的便携功能有哪些? 学习笔记 标准库中的常见组件 如何通过官方文档学习标准 from urllib.request import urlopen with urlopen(http://ww…...
基于yolov8的布匹缺陷检测系统,支持图像、视频和摄像实时检测【pytorch框架、python源码】
更多目标检测和图像分类识别项目可看我主页其他文章 功能演示: 基于yolov8的布匹缺陷检测系统,支持图像、视频和摄像实时检测【pytorch框架、python源码】_哔哩哔哩_bilibili (一)简介 基于yolov8的布匹缺陷检测系统是在 PyTo…...
SQL Server 中,将单行数据转换为多行数据
在 SQL Server 中,将单行数据转换为多行数据通常涉及到将某个字段中的逗号分隔的值拆分成多行。这种操作通常称为“拆分”或“展开”(Explode)。以下是一些常用的方法来实现这一目标: 1. 使用内置函数 STRING_SPLIT 从 SQL Serv…...
解决数组两数之和问题与逻辑推理找出谋杀案凶手
给定一个整数数组nums和一个整数目标值target(2<nums.length<10^4),请你在该数组中找出和为目标值target 的那两个整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。 你可以按任意顺序返…...
uniapp的IOS证书申请(测试和正式环境)及UDID配置流程
1.说明 本教程只提供uniapp在ios端的证书文件申请(包含正式环境和开发环境)、UDID配置说明,请勿用文档中的账号和其他隐私数据进行测试,请勿侵权! 2.申请前准备 证书生成网站:苹果应用上传、解析&#x…...
windows 安装apex_Nvidia Apex安装
参见windows 安装apex_Nvidia Apex安装 重点: 1、在安装前先检查一下,电脑的cuda版本和pytorch内的cuda版本是否一样,不一样的话就把低版本的进行升级; $ git clone https://github.com/NVIDIA/apex$ cd apex2、在保证cuda版本一…...
Laravel5 抓取第三方网站图片,存储到本地
背景 近期发现,网站上的部分图片无法显示, 分析发现,是因为引用的第三方网站图片(第三方服务器证书已过期) 想着以后显示的方便 直接抓取第三方服务器图片,转存到本地服务器 思路 1. 查询数据表࿰…...
DevOps和CI/CD以及在微服务架构中的作用
DevOps 和 CI/CD 是现代软件开发和运维中两个重要的概念,它们之间有紧密的联系,但也有不同的侧重点。以下是对这两个概念的详细介绍和比较。 1. DevOps 定义: DevOps 是一种文化、运动和实践,旨在通过促进开发(Development)和运维(Operations)团队之间的协作,提升软…...
Rust 力扣 - 5. 最长回文子串
文章目录 题目描述题解思路题解代码题解链接 题目描述 题解思路 从中心点先寻找和中心点相等的左右端点,在基于左右端点进行往外扩散,直至左右端点不相等或者越界,然后左右端点这个范围内就是我们找寻的回文串,我们遍历中心点&am…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
