Android 展示控件之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的关系
一、Surface
Surface在SDK的文档中的描述是这样的:Handle onto a raw buffer that is being managed by the screen compositor,翻译成中文就是“由屏幕显示内容合成器(screen compositor)所管理的原生缓冲器的句柄”。这句话包括如下两个意思:
- 通过Surface(因为Surface是句柄)就可以获得原生缓冲器以及其中的内容。就像在C语言中,可以通过一个文件的句柄,就可以获得文件的内容一样;
- 原生缓冲器(rawbuffer)是用于保存当前窗口的像素数据的。
也就是说Android中的Surface就是一个用来画图形(graphics)或图像(image)的地方。根据Java方面的常规知识,我们知道通常画图是在一个Canvas对象上面进行的,所以我们可以推测一个Surface对象中应该包含有一个Canvas对象,而事实也确实如此,通过查看Surface的源码可以证明:
***
private final Canvas mCanvas = new CompatibleCanvas();
***
Surface中的Canvas成员专门用于供程序员画图的场所,就像黑板一样;其中的原生缓冲器是用来保存数据的地方;Surface本身的作用类似一个句柄,得到了这个句柄就可以得到其中的Canvas、原生缓冲器以及其它方面的内容。
每个Surface都是双缓冲,它有一个backBuffer和一个frontBuffer,Surface中创建了Canvas对象,用来管理Surface绘图操作,Canvas对应Bitmap,存储Surface中的内容。所以使用Surface进行绘制的流程为:
- 创建一个Bitmap对象。
- 创建一个Canvas对象关联创建的Bitmap对象。
- 在Canvas上进行绘制。
- 锁定Canvas画布。
- 将Bitmap内容绘制到backBuffer中去。
- 解锁Canvas画布。
二、SurfaceView
SurfaceView是视图类View的子类,且实现了Parcelable接口且实现了Parcelable接口,其中内嵌了一个专门用于绘制的Surface,SurfaceView可以控制这个Surface的格式和尺寸,以及Surface的绘制位置。可以理解为Surface就是管理数据的地方,SurfaceView就是展示数据的地方,而我们就是通过SurfaceView看到的Surface的部分或者全部内容,再换句话说就是Surface是用通过SurfaceView才能展示其中的内容,二者的关系图如下:

SurfaceView和View最本质的区别在于:SurfaceView支持在单独线程中重新绘制画面,而View必须在UI的主线程中更新画面。
三、SurfaceHolder
SurfaceHolder是一个接口,其作用类似于一个surace的监听器,提供访问和控制Surface的方法。通过下面三个回调方法可以监听Surface的创建、销毁或者改变。
SurfaceView中调用getHolder方法,可以获得当前SurfaceView中的surface对应的SurfaceHolder,SurfaceHolder中重要的方法有:
- abstract void addCallback(SurfaceHolder.Callback callback ):为SurfaceHolder添加一个SurfaceHolder.Callback回调接口。
- abstract Canvas lockCanvas() :获取Surface中的Canvas对象,并锁定之。所得到的Canvas对象,其实就是Surface中一个成员。
- abstract CanvaslockCanvas(Rectdirty):同上。但只锁定dirty所指定的矩形区域,因此效率更高。
- abstract void unlockCanvasAndPost(Canvas canvas):当修改Surface中的数据完成后,释放同步锁,并提交改变,然后将新的数据进行展示。
- public abstract void setType (int type):设置Surface的类型。
从设计模式的角度来看,Surface、SurfaceView和SurfaceHolder实质上就是广为人知的MVC,即Model-View-Controller。Model就是模型的意思,或者说是数据模型,或者更简单地说就是数据,也就是这里的Surface;View即视图,代表用户交互界面,也就是这里的SurfaceView;SurfaceHolder很明显可以理解为MVC中的Controller(控制器)。这样再看三者之间的关系就清楚了很多。
四、SurfaceHolder.Callback
SurfaceHolder.Callback是SurfaceHolder接口内部的静态子接口,SurfaceHolder.Callback中定义了三个接口方法:
- public void sufaceChanged(SurfaceHolder holder,int format,int width,int height){}:Surface的大小发生改变时调用。
- public void surfaceCreated(SurfaceHolder holder){}:Surface创建时触发,一般在这里调用画面的线程。
- public void surfaceDestroyed(SurfaceHolder holder){}:销毁时触发,一般在这里将画面的线程停止、释放。
注意:所有SurfaceView和SurfaceHolder.Callback中声明的方法,必须在运行SurfaceView窗口中的线程中调用(即UI线程),因为它们需要正确地将同时被绘制线程访问的各种状态进行同步。
Android 展示控件之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的关系的更多相关文章
- C#中“类似GridView等控件”的前台显示与后台数据变化之间的关系
最近用dev的treelist,gridcontrol等控件,这些控件显示数据都需要进行DataTable等数据源的绑定,而经理又要求可以随时更改其中的内容,刚开始总是不断的刷新控件.更新控件的数据源 ...
- Android微信九宫格图片展示控件
版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/214 Android微信九宫格图片展示控件 半年前,公司产 ...
- Android 基本控件相关知识整理
Android应用开发的一项重要内容就是界面开发.对于用户来说,不管APP包含的逻辑多么复杂,功能多么强大,如果没有提供友好的图形交互界面,将很难吸引最终用户.作为一个程序员如何才能开发出友好的图形界 ...
- 【Android开发日记】之入门篇(十三)——Android的控件解析
Android的控件都派生自android.view.View类,在android.widget包中定义了大量的系统控件供开发者使用,开发者也可以从View类及其子类中,派生出自定义的控件. 一.An ...
- Android 开源控件与常用开发框架开发工具类
Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...
- Android基本控件Spinner的简单使用【转】
Android基本控件Spinner的简单使用 感谢大佬:https://blog.csdn.net/bingocoder/article/details/80469939 学习过了Textview, ...
- android 基础控件(EditView、SeekBar等)的属性及使用方法
android提供了大量的UI控件,本文将介绍TextView.ImageView.Button.EditView.ProgressBar.SeekBar.ScrollView.WebView ...
- Android基本控件之Menus
在我们的手机中有很多样式的菜单,比如:我们的短信界面,每条短信,我们长按都会出现一个菜单,还有很多的种类.那么现在,我们就来详细的讨论一下安卓中的菜单 Android的控件中就有这么一个,叫做Menu ...
- Android:控件布局(相对布局)RelativeLayout
RelativeLayout是相对布局控件:以控件之间相对位置或相对父容器位置进行排列. 相对布局常用属性: 子类控件相对子类控件:值是另外一个控件的id android:layout_above-- ...
随机推荐
- 53-java中的queue
java.util 接口 Queue<E> 类型参数: E - collection 中所保存元素的类型. 所有超级接口: Collection<E>, Iterable< ...
- mysql执行sql语句过程
开发人员基本都知道,我们的数据存在数据库中(目前最多的是mysql和oracle,由于作者更擅长mysql,所以这里默认数据库为mysql),服务器通过sql语句将查询数据的请求传入到mysql数据库 ...
- vue中v-model 与 v-bind:value
之前一直认为,v-model相当于下方代码的语法糖,如下: <h1>{{inputValue}}</h1> <input type="text" :v ...
- hbase_存储模型
Hbase 是按列存储,所以每个列族存储在一个HDFS文件上. Hbase表中的行是按照rowkey字典序进行排列的,并且表格在行的方向上被分割为多个region(按照行进行分割的) region 是 ...
- python中print不换行
python中的print打印的结果总是进行了换行,如果不想换行显示可以在print中添加“end ='' ” 一般print显示: for i in range(3): print(i) #显示结果 ...
- 【Python】 Python3 环境搭建
Python是一种计算机程序设计语言.是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的.大型项目的开发. Windo ...
- 小程序跳转tabbar页面
如果在app.json 配置tabbar 的时候配置了 跳转的页面的链接: 在其余的子页面,设置用navigator 进行跳转会发现 在tabbar 设置过的页面无法进行跳转,这时需要在navigat ...
- nginx上传文件时 nginx 413 Request Entity Too Large 错误
产生原因: 上传文件的大小超出了 Nginx 允许的最大值,默认是1M: 解决方法: 修改Nginx的配置文件(一般是:nginx/nginx.conf),在 http{} 段中增大nginx上传文件 ...
- WindowsPE权威指南 第二章 小工具 pedump代码的C语言实现
2016-11-16 16:29:07 主程序代码 pedump.c #include <windows.h> #include <Richedit.h> #include & ...
- 效果监控js源码
function _bxmPlatformFn(e, t) { var n, o, i = ""; try { i = localStorage.getItem("lis ...