一、Surface

Surface在SDK的文档中的描述是这样的:Handle onto a raw buffer that is being managed by the screen compositor,翻译成中文就是“由屏幕显示内容合成器(screen compositor)所管理的原生缓冲器的句柄”。这句话包括如下两个意思:

  1. 通过Surface(因为Surface是句柄)就可以获得原生缓冲器以及其中的内容。就像在C语言中,可以通过一个文件的句柄,就可以获得文件的内容一样;
  2. 原生缓冲器(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进行绘制的流程为:

  1. 创建一个Bitmap对象。
  2. 创建一个Canvas对象关联创建的Bitmap对象。
  3. 在Canvas上进行绘制。
  4. 锁定Canvas画布。
  5. 将Bitmap内容绘制到backBuffer中去。
  6. 解锁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中重要的方法有:

  1. abstract  void addCallback(SurfaceHolder.Callback callback ):为SurfaceHolder添加一个SurfaceHolder.Callback回调接口。
  2. abstract  Canvas lockCanvas() :获取Surface中的Canvas对象,并锁定之。所得到的Canvas对象,其实就是Surface中一个成员。
  3. abstract CanvaslockCanvas(Rectdirty):同上。但只锁定dirty所指定的矩形区域,因此效率更高。
  4. abstract  void unlockCanvasAndPost(Canvas canvas):当修改Surface中的数据完成后,释放同步锁,并提交改变,然后将新的数据进行展示。
  5. 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之间的关系的更多相关文章

  1. C#中“类似GridView等控件”的前台显示与后台数据变化之间的关系

    最近用dev的treelist,gridcontrol等控件,这些控件显示数据都需要进行DataTable等数据源的绑定,而经理又要求可以随时更改其中的内容,刚开始总是不断的刷新控件.更新控件的数据源 ...

  2. Android微信九宫格图片展示控件

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/214 Android微信九宫格图片展示控件 半年前,公司产 ...

  3. Android 基本控件相关知识整理

    Android应用开发的一项重要内容就是界面开发.对于用户来说,不管APP包含的逻辑多么复杂,功能多么强大,如果没有提供友好的图形交互界面,将很难吸引最终用户.作为一个程序员如何才能开发出友好的图形界 ...

  4. 【Android开发日记】之入门篇(十三)——Android的控件解析

    Android的控件都派生自android.view.View类,在android.widget包中定义了大量的系统控件供开发者使用,开发者也可以从View类及其子类中,派生出自定义的控件. 一.An ...

  5. Android 开源控件与常用开发框架开发工具类

    Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...

  6. Android基本控件Spinner的简单使用【转】

    Android基本控件Spinner的简单使用 感谢大佬:https://blog.csdn.net/bingocoder/article/details/80469939 学习过了Textview, ...

  7. android 基础控件(EditView、SeekBar等)的属性及使用方法

        android提供了大量的UI控件,本文将介绍TextView.ImageView.Button.EditView.ProgressBar.SeekBar.ScrollView.WebView ...

  8. Android基本控件之Menus

    在我们的手机中有很多样式的菜单,比如:我们的短信界面,每条短信,我们长按都会出现一个菜单,还有很多的种类.那么现在,我们就来详细的讨论一下安卓中的菜单 Android的控件中就有这么一个,叫做Menu ...

  9. Android:控件布局(相对布局)RelativeLayout

    RelativeLayout是相对布局控件:以控件之间相对位置或相对父容器位置进行排列. 相对布局常用属性: 子类控件相对子类控件:值是另外一个控件的id android:layout_above-- ...

随机推荐

  1. 解析ReentrantLock实现原理

    在Java中通常实现锁有两种方式,一种是synchronized关键字,另一种是Lock(Lock的实现主要有ReentrantLock.ReadLock和WriteLock).synchronize ...

  2. 机器学习--Lasso回归和岭回归

    之前我们介绍了多元线性回归的原理, 又通过一个案例对多元线性回归模型进一步了解, 其中谈到自变量之间存在高度相关, 容易产生多重共线性问题, 对于多重共线性问题的解决方法有: 删除自变量, 改变数据形 ...

  3. Struts2各个功能详解(2)-输入校验和拦截器

    前面知道了struts2的架构图和struts2的自动封装表单参数和数据类型自动转换,今天来学struts2的第三第四个东西,输入校验和拦截器.  一:输入校验 客户端校验进行基本校验,如检验非空字段 ...

  4. Swift Realm 完整使用记录

    新项目用到了数据库,本来之前用的都是 SQL,但是语法写的实在是恶心,所以使用 Realm 尝试一下. 1.我使用的 pod 库,所以先 pod 库安装一下,安装完别忘了先编译一下,不然 import ...

  5. IIS发布MVC ASP.NET网站

    发布网站后,发现无法访问,最后在配置文件上添加一段: <system.codedom> <compilers> <compiler language="c#;c ...

  6. 安装mysql后,sql语句中表名区分大小写的问题

    今天安装完mysql后,执行查询语句select * from user,结果报user表不存在,但是实际是存在的,查了一下才知道是因为mysql的my.cnf文件中少了一个大小写敏感的配置,若不配置 ...

  7. Linux查看机器负载

    负载(load)是linux机器的一个重要指标,直观了反应了机器当前的状态.如果机器负载过高,那么对机器的操作将难以进行. Linux的负载高,主要是由于CPU使用.内存使用.IO消耗三部分构成.任意 ...

  8. oracle 数据库去重复数据

    delete from 表名 a where rowid !=(select max(rowid) from 表名 b where a.ORDER_ID=b.ORDER_ID) 例:如果重复的数据表是 ...

  9. common skill

    lunix watch and kill progress 1.  ps -ef 2. kill -9 pid

  10. java学习(三)

    学号 20189214 <Java程序设计>第三周学习总结 教材学习内容总结 核心类 java.lang.Object 所有的类都直接派生自这个类. java.lang.String St ...