WMS:SurfaceView绘制显示
WMS:SurfaceView绘制显示
- 1、SurfaceView控件使用
- 1.1 Choreographer接受VSync信号
- 1.2 自定义SurfaceView
- 1.3 结果
- 2、SurfaceView获取画布并显示
- 2.1 SurfaceHolder.lockCanvas()
- 2.2 SurfaceHolder.unlockCanvasAndPost(Canvas canvas)
1、SurfaceView控件使用
1.1 Choreographer接受VSync信号
Choreographer是Android提供的一个获取VSync信号的通道。这里
SurfaceView控件是主动上屏绘制,而一般应用如
WMS中Choreographer 配合 VSYNC 中断信号 中添加界面时从 ViewRootImpl 的 scheduleTraversals 方法开始,其内部通过 Choreographer 的 postCallback 将绘制任务添加到 Chorographer。
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {//当vsync信号来时会调用到这里mHandler.sendEmptyMessage(MyHandler.TAG_UPDATE_TEXT);Choreographer.getInstance().removeFrameCallback(this);Choreographer.getInstance().postFrameCallback(this);}});
1.2 自定义SurfaceView
MySurfaceView构造函数中获取mSurfaceHolder = this.getHolder(),并设置SurfaceHolder.Callback- 继承
Runnable,Thread中运行,并Global.syncCondition.await();在这里等待vsync到来的通知消息- 线程并发处理
Lock和Condition:public class Global {public static ReentrantLock lock = new ReentrantLock();public static Condition syncCondition = lock.newCondition();private Global() {} }
Choreographer#doFrame中Global.syncCondition.signal();通知另一条线程更新画面
com/xhbruce/ui/MySurfaceView.java
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {private static String TAG = "MySurfaceView";private SurfaceHolder mSurfaceHolder;private int autoNum = 0;private Paint mPaint = new Paint();public MySurfaceView(Context context) {this(context, null);}public MySurfaceView(Context context, AttributeSet attrs) {this(context, attrs , 0);}public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mSurfaceHolder = this.getHolder();mSurfaceHolder.addCallback(this);Log.d(TAG, "MySurfaceView(3) holder=" + mSurfaceHolder.toString());}public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);mSurfaceHolder = this.getHolder();mSurfaceHolder.addCallback(this);Log.d(TAG, "MySurfaceView(4) holder=" + mSurfaceHolder.toString());}@Overridepublic void surfaceCreated(@NonNull SurfaceHolder holder) {Log.d(TAG, "surfaceCreated() holder=" + holder.toString());new Thread(this).start();
// draw();//画蓝色或绿色}@Overridepublic void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(@NonNull SurfaceHolder holder) {}@Overridepublic void run() {while (true) {Log.d(TAG, "run() autoNum=" + autoNum);Global.lock.lock();try {Global.syncCondition.await();//在这里等待vsync到来的通知消息} catch (InterruptedException e) {e.printStackTrace();} finally {Global.lock.unlock();}draw();//画蓝色或绿色}}private void draw() {Canvas mCanvas = null;try {mCanvas = mSurfaceHolder.lockCanvas();if (autoNum % 2 == 0) {mPaint.setColor(Color.BLUE);//如果为双数则画面画成蓝色} else {mPaint.setColor(Color.GREEN);//如果为单数则画面画成绿色}mCanvas.drawRect(0, 0, getRight(), getBottom(), mPaint);} catch (Exception e) {e.printStackTrace();} finally {if (mCanvas != null) {mSurfaceHolder.unlockCanvasAndPost(mCanvas);}}Log.d(TAG, "draw() autoNum=" + autoNum);autoNum++;//数字加1}
}
对应Activity和xml布局文件:
com/xhbruce/surfaceviewtest/MySurfaceViewTest.java
public class MySurfaceViewTest extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_my_surface_view_test);Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {//当vsync信号来时会调用到这里Global.lock.lock();try {Global.syncCondition.signal();//通知另一条线程更新画面} catch (Exception e) {e.printStackTrace();} finally {Global.lock.unlock();}Choreographer.getInstance().removeFrameCallback(this);Choreographer.getInstance().postFrameCallback(this);}});}
}
layout/activity_my_surface_view_test.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MySurfaceViewTest"><com.xhbruce.ui.MySurfaceViewandroid:layout_width="match_parent"android:layout_height="match_parent" />
</LinearLayout>
1.3 结果
SurfaceView Demo
2、SurfaceView获取画布并显示
- SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布
- SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。
2.1 SurfaceHolder.lockCanvas()
Surface的lock方法最终调用到
GraphicBufferProducer的dequeueBuffer函数获取一个Slot,如果Slot没有分配GraphicBuffer会在这时给它分配GraphicBuffer, 然后会返回一个带有BUFFER_NEEDS_REALLOCATION标记的flag, 应用侧看到这个flag后会通过requestBuffer和importBuffer接口把GraphicBuffer映射到自已的进程空间。

2.2 SurfaceHolder.unlockCanvasAndPost(Canvas canvas)
SurfaceView在更新视图时用到了两张Canvas,一张
frontCanvas和一张backCanvas,每次实际显示的是frontCanvas,backCanvas存储的是上一次更改前的视图,当使用lockCanvas()获取画布时,得到的实际上是backCanvas而不是正在显示的frontCanvas,之后你在获取到的backCanvas上绘制新视图,再unlockCanvasAndPost(Canvas canvas)此视图,那么上传的这张canvas将替换原来的frontCanvas作为新的frontCanvas,原来的frontCanvas将切换到后台作为backCanvas。

相关文章:
WMS:SurfaceView绘制显示
WMS:SurfaceView绘制显示 1、SurfaceView控件使用1.1 Choreographer接受VSync信号1.2 自定义SurfaceView1.3 结果 2、SurfaceView获取画布并显示2.1 SurfaceHolder.lockCanvas()2.2 SurfaceHolder.unlockCanvasAndPost(Canvas canvas) 1、SurfaceView控件使用 1.1 Choreograph…...
【Spring系列篇--关于IOC的详解】
目录 面试经典题目: 1. 什么是spring?你对Spring的理解?简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。 2.什么是IoC?你对IoC的理解?IoC的重要性?将实例化对象的权利从程序员…...
__ob__: Observer 后缀的数组的取值方式
开发中,经常从接口、父组件中,拿到数组然后给新的数组使用, 但是,有时候会发现带有 __ob__: Observer 后缀的数组,对这种数组来说,你是无法取到这个数组的值的, 而且,离谱的是consol…...
时序预测 | MATLAB实现WOA-CNN-BiLSTM鲸鱼算法优化卷积双向长短期记忆神经网络时间序列预测
时序预测 | MATLAB实现WOA-CNN-BiLSTM鲸鱼算法优化卷积双向长短期记忆神经网络时间序列预测 目录 时序预测 | MATLAB实现WOA-CNN-BiLSTM鲸鱼算法优化卷积双向长短期记忆神经网络时间序列预测预测效果基本介绍程序设计学习总结参考资料 预测效果 基本介绍 时序预测 | MATLAB实现…...
Java基础知识点
Java是一种高级计算机语言,是可以编写跨平台应用软件、完全面向对象的程序设计语言。 2、Java划分为三个技术平台:Java SE、Java EE、Java ME Java SE是桌面应用,Java EE是web应用,平台企业版,Java ME是手机应用&#…...
攻防世界-web-fileclude
1. 题目描述 打开链接,可以看到如下代码: 代码意思很简单,让我们传递两个参数,一个file1,一个file2,如果file2的内容为hello ctf,那么就可以在代码中include file1 2. 思路分析 这道题显然是…...
【100天精通python】Day36:GUI界面编程_高级功能操作和示例
专栏导读 专栏订阅地址:https://blog.csdn.net/qq_35831906/category_12375510.html 一、GUI 高级功能 1 自定义主题和样式 自定义主题和样式可以让你的GUI应用程序在外观方面更加出色。在使用Tkinter时,你可以使用ttkthemes库来应用不同的主题和样式。…...
无涯教程-Perl - sub函数
描述 此函数定义一个新的子例程。上面显示的参数遵循以下规则- NAME是子例程的名称。可以在有或没有原型规范的情况下预先声明命名的子例程(没有关联的代码块)。 匿名子例程必须具有定义。 PROTO定义了函数的原型,调用该函数以验证提供的参数时将使用该原型。 ATTRS为解析…...
wpf控件上移下移,调整子集控件显示顺序
页面代码: <!-- 导出A2,自定义导出设置列,添加时间:2023-8-9 14:14:18,作者:whl; --><Window x:Class="WpfSnqkGasAnalysis.WindowGasExportA2"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http:/…...
cesium学习记录08-鼠标绘制多边形
上一篇学习了实体的一些基础知识,这一篇来学习鼠标绘制实体多边形的实现 一、方法一: 1,结果显示 贴地: 不贴地: 2,方法全部代码: 主方法: /*** 绘制多边形* param {Object} op…...
rocketMq启动broker报错找不到或无法加载主类 Files\Java\jdk1.8.0_171\lib\dt.jar;C:\Program]
假如弹出提示框提示‘错误: 找不到或无法加载主类 xxxxxx’。 1.打开runbroker.cmd 将"%CLASSPATH%"加上英文双引号,切勿别加中文双引号 2.打开runserver.cmd 同理 将"%CLASSPATH%"加上英文双引号,切勿别加中文双引号 3.正常执行即…...
Linux touch 命令指南大全
1. 概述 在本教程中,我们将学习touch命令。简而言之,这个命令允许我们更新文件或目录的最后修改时间和最后访问时间。 因此,我们将重点关注如何使用该命令及其各种选项。 请注意,我们使用 Bash 测试了此处显示的所有命令;但是,它们应该与任何兼容 POSIX 的 shell 一起使…...
华为网络篇 RIPv2的基础配置-25
难度 1复杂度1 目录 一、实验原理 1.1 RIP的版本 1.2 RIP的路由更新方式 1.3 RIP的计时器 1.4 RIP的防环机制 二、实验拓扑 三、实验步骤 四、实验过程 总结 一、实验原理 RIP(Routing Information Protocol,路由信息协议)&am…...
fastadmin 下拉多级分类
要实现下图效果 一、先创建数据表 二、在目标的controll中引入use fast\Tree; public function _initialize() {parent::_initialize();$this->model new \app\admin\model\zxdc\Categorys;$tree Tree::instance();$tree->init(collection($this->model->order(…...
时序预测 | MATLAB实现基于CNN-LSTM卷积长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价)
时序预测 | MATLAB实现基于CNN-LSTM卷积长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价) 目录 时序预测 | MATLAB实现基于CNN-LSTM卷积长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价)预测结果基本介绍程序设计参考资料 预测结果 基本介绍 MATLAB实现基…...
RabbitMQ工作流程详解
1 生产者发送消息的流程 (1)生产者连接RabbitMQ,建立TCP连接(Connection),开启信道(Channel) (2)生产者声明一个Exchange (交换器),并设置相关属性,比如交换器类型、是否持久化等 (3)生产者声明一个队列井设置相关属性…...
LabVIEW使用图像处理进行交通控制性能分析
LabVIEW使用图像处理进行交通控制性能分析 采用普雷维特、拉普拉斯、索贝尔和任意的空间域方法对存储的图像进行边缘检测,并获取实时图像。然而,对四种不同空间域边缘检测方法的核的性能分析。 以前,空路图像存储在数据库中,道路…...
CentOS 7 下 Keepalived + Nginx 实现双机高可用
CentOS 7 下 Keepalived Nginx 实现双机高可用 文章目录 CentOS 7 下 Keepalived Nginx 实现双机高可用服务器准备服务信息服务架构 服务安装nginxKeepalived 服务配置nginxKeepalived 启动服务nginxkeepalived 服务验证查看 VIP 状态CURL 命令访问浏览器访问 高可用验证停止…...
【Linux】IO多路转接——select接口
目录 I/O多路转接之select select初识 select函数 socket就绪条件 select基本工作流程 select服务器 select的优点 select的缺点 select的适用场景 I/O多路转接之select select初识 select是系统提供的一个多路转接接口。 select系统调用可以让我们的程序同时监视多…...
error_Network Error
此页面为订单列表,是混合开发(页面嵌入在客户端中) 此页面为订单列表,此需求在开发时后端先将代码发布在测试环境,我在本地调试时调用的后端接口进行联调没有任何问题。 此后我将代码发布在测试环境,在app中打开页面,…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
