android.view.View 和 android.view.SurfaceView

SurfaceView 是从 View 基类中派生出来的显示类,直接子类有 GLSurfaceView和VideoView ,可以
看出 GL 和视频播放以及 Camera 摄像头一般均使用 SurfaceView
View获得焦点:setFocusable(true);


在继承view中,因为onDraw方法是系统自动调用的,不像在surfaceview这里这样去在run里面自己去不断调用,在view中我们可以抵用 invalidate()/postInvalidate() 这两种方法实现让系统调用onDraw方法,这里也是和surfaceview中的不同之一!

 

SurfaceView和View最本质的区别

surfaceView 是在一个新起的单独线程中可以重新绘制画面而 View 必须在 UI 的主线程中更新画面。

SurfaceView 和 View 用处
1 被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。

2 主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。

3.Android中的SurfaceView类就是双缓冲机制。因此,开发游戏时尽量使用SurfaceView而不要使用View,这样的话效率较高,而且SurfaceView的功能也更加完善。

考虑以上几点,所以我一直都选用 SurfaceView 来进行游戏开发。

SurfaceView 优势

SurfaceView 可以控制表面的格式,比如大小,显示在屏幕中的位置,最关键是的提供了 SurfaceHolder 类,使用 getHolder 方法获取,相关有
Canvas lockCanvas(),  Canvas lockCanvas(Rect dirty) 、void removeCallback(SurfaceHolder.Callback callback)、void unlockCanvasAndPost(Canvas canvas) 控制图形以及绘制,而在SurfaceHolder.Callback 接口回调中可以通过重写下面方法实现。 

使用的SurfaceView的时候,一般情况下要对其进行创建,销毁,改变时的情况进行监视,这就要用到 SurfaceHolder.Callback. 
class XxxView extends SurfaceView implements SurfaceHolder.Callback {

public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){} 
//看其名知其义,在surface的大小发生改变时激发 
public void surfaceCreated(SurfaceHolder holder){} 
//同上,在创建时激发,一般在这里调用画图的线程。 
public void surfaceDestroyed(SurfaceHolder holder) {} 
//同上,销毁时激发,一般在这里将画图的线程停止、释放。

}

对于Surface相关的,Android底层还提供了 GPU 加速功能,所以一般实时性很强的应用中主要使用 SurfaceView 而不是直接从 View 构建,同时后来做 android 3d OpenGL 中的 GLSurfaceView 也是从该类实现。 


surfaceview 的结构


备注1

callback接口:

只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView了,SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知View,SurfaceHolder.Callback具有如下的接口:

  • surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作,一般情况下都是在另外的线程来绘制界面,所以不要在这个函数中绘制Surface。
  • surfaceChanged(SurfaceHolder holder, int format, int width,int height):当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。

SurfaceHolder 类:

它是一个用于控制surface的接口,它提供了控制surface 的大小,格式,上面的像素,即监视其改变的。

SurfaceView的getHolder()函数可以获取SurfaceHolder对象,Surface 就在SurfaceHolder对象内。虽然Surface保存了当前窗口的像素数据,但是在使用过程中是不直接和Surface打交道的,由SurfaceHolder的Canvas lockCanvas()或则Canvas lockCanvas()函数来获取Canvas对象,通过在Canvas上绘制内容来修改Surface中的数据。如果Surface不可编辑或则尚未创建调用该函数会返回null,在 unlockCanvas() 和 lockCanvas()中Surface的内容是不缓存的,所以需要完全重绘Surface的内容,为了提高效率只重绘变化的部分则可以调用lockCanvas(Rect rect)函数来指定一个rect区域,这样该区域外的内容会缓存起来。在调用lockCanvas函数获取Canvas后,SurfaceView会获取Surface的一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁,这里的同步机制保证在Surface绘制过程中不会被改变(被摧毁、修改)。

// 备注2

我没有在该surfaceview的初始化函数中将其 ScreenW 与 ScreenH 进行赋值,这里要特别注意,如果你在初始化调用ScreenW = this.getWidth();和ScreenH = this.getHeight();那么你将得到很失望的值 全部为0;原因是和接口Callback接口机制有关,当我们继承callback接口会重写它的surfaceChanged()、surfaceCreated()、surfaceDestroyed(),这几个函数当surfaceCreated()被执行的时候,真正的view才被创建,也就是说之前得到的值为0 ,是因为初始化会在surfaceCreated()方法执行以前执行,view没有的时候我们去取屏幕宽高肯定是0,所以这里要注意这一点;

//备注3

这里我把draw的代码都try起来,主要是为了当画的内容中一旦抛出异常了,那么我们也能 在finally中执行该操作。这样当代码抛出异常的时候不会导致Surface出去不一致的状态。

其实这就是一个简单的游戏架构了,当然还少了按键处理,声音播放等等,这些我后续会写出相关的学习文章。对于surfaceview的介绍差不多就介绍到这里了,其中的理解是看了别人的文章和自己的理解、当然可能理解的会有些偏差,但是我想不会太离谱 呵呵。


SurfaceView 和 View 区别的更多相关文章

  1. SurfaceView 与view区别详解

    SurfaceView 与view区别详解 https://blog.csdn.net/u011339364/article/details/83347109 2018年10月24日 17:20:08 ...

  2. android: View, SurfaceView, GLSurfaceView, TextureView 区别与联系

    区别与联系 View: 显示视图,内置画布,提供了图形绘制函数.触屏事件.按键事件函数等,必须在UI主线程内更新画面,速度较慢: SurfaceView: 基于view视图进行拓展的视图类,更适合2D ...

  3. Android SurfaceView与View

    SurfaceView介绍 SurfaceView是视图(View)的继承类,这个视图里面内嵌了一个专门用于绘制的Surface.你可以控制这个Surface的格式和尺寸,而SurfaceView控制 ...

  4. surfaceView和View的区别

    概念:view在UI线程去更新自己:而SurfaceView则在一个子线程中去更新自己 surfaceView是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面 在UI的 ...

  5. 转--Invalidate和postInvalidate的更新view区别

    Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用. Android提供了Inva ...

  6. Andrid 高级程序员面试题

    ==========================20150518===================================一. Acitvity组件 1. 生命周期&kille ...

  7. 墙裂推荐!2020Android阿里&腾讯&百度&字节&美团校招面试汇总

    基本情况 2021届硕士生,Android开发岗 此文主要是2020年年初春招实习的面试和正式校招面试经验汇总,最终校招拿到了腾讯,百度,美团等offer 主要包括阿里4面,腾讯实习4面和校招4面,字 ...

  8. view,SurfaceView,GLSurfaceView的关系和区别

    如果你的游戏不吃CPU,用View就比较好,符合标准Android操作方式,由系统决定刷新surface的时机. 但如果很不幸的,你做不到不让你的程序吃CPU,你就只好使用SurfaceView来强制 ...

  9. Android之View和SurfaceView

    Android之View和SurfaceView Android游戏当中主要的除了控制类外就是显示类View.SurfaceView是从View基类中派生出来的显示类.android游戏开发中常用的三 ...

随机推荐

  1. linux里的bootproto的none,static,dhcp有什么区别

      这个是网络配置参数:BOOTPROTO=static 静态IP BOOTPROTO=dhcp 动态IP BOOTPROTO=none 无(不指定)通常情况下是dhcp或者static,通过指定方式 ...

  2. ListView学习小结

    ListView小结 ListView 是Android UI中十分重要的一个组件,在数据的显示上能有着十分灵活的表现,其使用也比较简单,一般包括以下几个要点: 1.  可以通过编写ListActiv ...

  3. 第二章 andrid studio创建项目

    原文 http://blog.csdn.net/zhanghefu/article/details/9326735 第二章 andrid studio创建项目 第二章 andrid studio创建项 ...

  4. Gradle DSL method not found: 'android()

    原文错误提示: Error:(16, 0) Gradle DSL method not found: 'android()'Possible causes:<ul><li>Th ...

  5. Linux中service命令和/etc/init.d/的关系

    Linux中service命令和/etc/init.d/的关系   service xxx启动 /etc/init.d/ 目录下的xxx脚本 如一个脚本名为 mysvc保存在/etc/init.d/下 ...

  6. 推荐一些C#相关的网站、资源和书籍(转载)

    原文地址:http://blog.csdn.net/chinacsharper/article/details/17514923 一.网站 1.http://msdn.microsoft.com/zh ...

  7. JavaWeb学习—Servlet

    1.什么是Servlet Servlet是一个继承HttpServlet类的Java类 Servlet必须部署在web服务器端,用来处理客户端的请求 2.Servlet运行过程 Web Client ...

  8. Flash,一次Bug的思考

    我绝对不算是F黑,大部分时候,我还是很挺Flash平台的,Flash提供了很好的跨平台特性以及Flash Player11后的GPU加速.Stage3D等等,对于开发者来说,绝对让人欣喜若狂(对我是这 ...

  9. C#获取单个字符的拼音声母

    public class ConvertToPinYing     {         /// <summary>         /// 汉字转拼音缩写         /// < ...

  10. CodeFirst EF中导航属性的个人理解

    >导航属性: 01.个人理解就是Ef中的属性在实体数据表中不存在(先这么认为); 02.就是除了根据表中列映射出的属性 之外根据表与表之间的关系的关联属性.方便操作与之关联的表; 例如: 有 表 ...