一、什么是Surface

简单的说Surface对应了一块屏幕缓冲区,每个window对应一个Surface,任何View都要画在Surface的Canvas上(后面有原因解释)。传统的view共享一块屏幕缓冲区,所有的绘制必须在UI线程中进行。

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

1、通过Surface(因为Surface是句柄)就可以获得原生缓冲器以及其中的内容。就像在C++语言中,可以通过一个文件的句柄,就可以获得文件的内容一样。

2、 原始缓冲区(a raw buffer)是用于保存当前窗口的像素数据的。

引伸地,可以认为Android中的Surface就是一个用来画图形(graphics)或图像(image)的地方。

根据Java方面的常规知识,我们知道通常画图是在一个Canvas对象上面进行的,由此,可以推知一个Surface对象中应该包含有一个Canvas(画布)对象。因此,在前面提及的两个意思的基础上,可以再加上一条:

3、Surface中有一个Canvas成员,专门用于画图的。

由以上的概括,我们总结如下:Surface中的Canvas成员,是专门用于供程序员画图的场所,就像黑板一样;其中的原始缓冲区是用来保存数据的地方;Surface本身的作用类似一个句柄,得到了这个句柄就可以得到其中的Canvas、原始缓冲区以及其它方面的内容。

Surface是用来管理数据的。(句柄)

二、什么是SurfaceView

说SurfaceView是一个View也许不够严谨,然而从定义中pubilc classSurfaceView extends View{.....}显示SurfaceView确实是派生自View,但是SurfaceView却有自己的Surface,请看SurfaceView的源码:

  1. <span style="font-size:14px;color:#333333;">   if (mWindow == null) {
    mWindow = new MyWindow(this);
    mLayout.type = mWindowType;
    mLayout.gravity = Gravity.LEFT|Gravity.TOP;
    mSession.addWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
    mVisible ? VISIBLE : GONE, mContentInsets);
    } </span>

很明显,每个SurfaceView创建的时候都会创建一个MyWindow,new MyWindow(this)中的this正是SurfaceView自身,因此将SurfaceView和window绑定在一起,由第一部分我们知道,一个window对应一个Surface,因此SurfaceView也就内嵌了一个自己的Surface,可以认为SurfaceView是用来控制Surface中View的位置和尺寸的。

SurfaceView就是展示Surface中数据的地方,同时可以认为SurfaceView是用来控制Surface中View的位置和尺寸的。

大家都知道,传统View及其派生类的更新只能在UI线程,然而UI线程还同时处理其他交互逻辑,这就无法保证View更新的速度和帧率了,而SurfaceView可以用独立的线程进行绘制,因此可以提供更高的帧率,例如游戏,摄像头取景等场景就比较适合SurfaceView来实现。

三、什么是SurfaceHolder

SurfaceHolder是一个接口,其作用就像一个关于Surface的监听器,提供访问和控制SurfaceView内嵌的Surface 相关的方法。它通过三个回调方法,让我们可以感知到Surface的创建、销毁或者改变。

在SurfaceView中有一个方法getHolder,可以很方便地获得SurfaceView内嵌的Surface所对应的监听器接口SurfaceHolder(有点拗口吧)。

除下面将要提到的SurfaceHolder.Callback外,SurfaceHolder还提供了很多重要的方法,其中最重要的就是:

1、abstract void addCallback(SurfaceHolder.Callbackcallback):为SurfaceHolder添加一个SurfaceHolder.Callback回调接口。

2、abstract Canvas lockCanvas():获取一个Canvas对象,并锁定之。所得到的Canvas对象,其实就是Surface中一个成员。

3、abstract Canvas lockCanvas(Rect  dirty):同上。但只锁定dirty所指定的矩形区域,因此效率更高。

4、abstract void unlockCanvasAndPost(Canvas  canvas):当修改Surface中的数据完成后,释放同步锁,并提交改变,然后将新的数据进行展示,同时Surface中相关数据会被丢失。

2、3、4中的同步锁机制的目的,就是为了在绘制的过程中,Surface中的数据不会被改变。lockCanvas是为了防止同一时刻多个线程对同一canvas写入。

总结:从设计模式的高度来看,Surface、SurfaceView和SurfaceHolder实质上就是广为人知的MVC,即Model-View-Controller。Model就是模型的意思,或者说是数据模型,或者更简单地说就是数据,也就是这里的Surface;View即视图,代表用户交互界面,也就是这里的SurfaceView;SurfaceHolder很明显可以理解为MVC中的Controller(控制器)。

四、什么是SurfaceHolder.Callback

SurfaceHolder.Callback主要是当底层的Surface被创建、销毁或者改变时提供回调通知,由于绘制必须在Surface被创建后才能进行,因此SurfaceHolder.Callback中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界。

SurfaceHolder.Callback中定义了三个接口方法:

1、abstract void surfaceChanged(SurfaceHolder holder, int format, int width, int height):当surface发生任何结构性的变化时(格式或者大小),该方法就会被立即调用。

2、abstract void surfaceCreated(SurfaceHolder holder):当surface对象创建后,该方法就会被立即调用。

3、abstract void  surfaceDestroyed(SurfaceHolder holder):当surface对象在将要销毁前,该方法会被立即调用。

五、实例演示

下面,我们通过一个非常简单例子来实际感受一下,请留意代码中的注释:

1、在Eclipse中创建一个Android Project项目TestSurfaceView,并选择生成缺省的Activity TestSurfaceViewActivity

2、创建一个绘制线程如下:

  1. import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    importandroid.view.SurfaceHolder; // 绘制线程
    public class MyThread extends Thread
    {
    private SurfaceHolder holder;
    private boolean run; public MyThread(SurfaceHolder holder)
    {
    this.holder = holder;
    run = true;
    } @Override
    public void run()
    {
    int counter = 0;
    Canvas canvas = null;
    while(run)
    {
    // 具体绘制工作
    try
    {
    // 获取Canvas对象,并锁定之
    canvas= holder.lockCanvas(); // 设定Canvas对象的背景颜色
    canvas.drawColor(Color.WHITE); // 创建画笔
    Paint p = new Paint();
    // 设置画笔颜色
    p.setColor(Color.BLACK);
    // 设置文字大小
    p.setTextSize(30); // 创建一个Rect对象rect
    Rect rect = new Rect(100, 50, 380, 330);
    // 在canvas上绘制rect
    canvas.drawRect(rect,p);
    // 在canvas上显示时间
    canvas.drawText("Interval = " + (counter++) + " seconds.", 100, 410, p);
    Thread.sleep(1000);
    }
    catch(Exception e)
    {
    e.printStackTrace();
    }
    finally
    {
    if(canvas != null)
    {
    // 解除锁定,并提交修改内容
    holder.unlockCanvasAndPost(canvas);
    }
    }
    }
    } public boolean isRun()
    {
    return run;
    } public void setRun(boolean run)
    {
    this.run = run;
    }
    }

3、自定义一个SurfaceView类如下:

  1.  import android.content.Context;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView; public class MySurfaceView extends SurfaceView<span style="font-family:Arial;"> </span>implements<span style="font-family:Arial;"> </span>SurfaceHolder.Callback
    {
    private SurfaceHolder holder;
    private MyThread myThread; public MySurfaceView(Context context)
    {
    super(context); // 通过SurfaceView获得SurfaceHolder对象
    holder = getHolder(); // 为holder添加回调结构SurfaceHolder.Callback
    holder.addCallback(this); // 创建一个绘制线程,将holder对象作为参数传入,这样在绘制线程中就可以获得holder
    // 对象,进而在绘制线程中可以通过holder对象获得Canvas对象,并在Canvas上进行绘制
    myThread = new MyThread(holder);
    } // 实现SurfaceHolder.Callback接口中的三个方法,都是在主线程中调用,而不是在绘制线程中调用的
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {
    } @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
    // 启动线程。当这个方法调用时,说明Surface已经有效了
    myThread.setRun(true);
    myThread.start();
    } @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
    // 结束线程。当这个方法调用时,说明Surface即将要被销毁了
    myThread.setRun(false);
    }
    }

4、修改TestSurfaceViewActivity.java代码,使之如下:

      1import android.app.Activity;

  1.  import android.os.Bundle;  
    
     public class TestSurfaceViewActivity extends Activity
    {
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    //setContentView(R.layout.main);
    setContentView(new MySurfaceView(this));
    }
    }

运行结果:

原文:http://blog.csdn.net/tgww88/article/details/7973476

Android中的Surface和SurfaceView的更多相关文章

  1. Android中的Surface, SurfaceHolder, SurfaceHolder.Callback, SurfaceView

    传入一个surface,然后让openGL在surface上画图 window->view hierachy(DecorView是tree的root)->ViewRoot->Surf ...

  2. Android图形系统之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback开发实例

    原文:Android图形系统之Surface.SurfaceView.SurfaceHolder及SurfaceHolder.Callback之间的联系 Surface是原始图像缓冲区(raw buf ...

  3. Android图形系统之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的联系

    1.Surface Surface extends Objectimplements Parcelable java.lang.Object    ↳ android.view.Surface Cla ...

  4. android中使用MediaPlayer和SurfaceView播放视频

    package com.test.video; import java.io.IOException; import android.media.AudioManager; import androi ...

  5. Android 展示控件之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的关系

    一.Surface Surface在SDK的文档中的描述是这样的:Handle onto a raw buffer that is being managed by the screen compos ...

  6. Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的关系

    转载请包含网址:http://blog.csdn.net/pathuang68/article/details/7351317 一.Surface Surface就是“表面”的意思.在SDK的文档中, ...

  7. Android多媒体之view,SurfaceView,GLSurfaceView

    1.相关概念 不用画布,直接在窗口上进行绘图叫做无缓冲绘图. 用了一个画布,将所有内容都先画到画布上,在整体绘制到窗口上,就该叫做单缓冲绘图, 那个画布就是一个缓冲区.用了两个画布,一个进行临时的绘图 ...

  8. 深入浅出Android开发之Surface介绍

    一 目的 本节的目的就是为了讲清楚Android中的Surface系统,大家耳熟能详的SurfaceFlinger到底是个什么东西,它的工作流程又是怎样的.当然,鉴于SurfaceFlinger的复杂 ...

  9. Android捕捉图像后在SurfaceView上变形显示问题的处理

    我们在Android中经常会使用SurfaceView编写自定义的摄像头,可是有的时候会经常会出现图像的变形,我们就会很郁闷的问这到底是为什么呢?其实这个最根本的原因是SurfaceView和PreV ...

随机推荐

  1. 最精简的代理设计模式demo - 保姆看孩子

    1,协议文件 @protocol NursePtotocol <NSObject> //保姆的协议方法 - (void)startToAmuseBaby; @end 2,管理类(使用类) ...

  2. Solr4.8.0源码分析(24)之SolrCloud的Recovery策略(五)

    Solr4.8.0源码分析(24)之SolrCloud的Recovery策略(五) 题记:关于SolrCloud的Recovery策略已经写了四篇了,这篇应该是系统介绍Recovery策略的最后一篇了 ...

  3. 转:windows下使用gvim搭建简单的IDE编译环境(支持C/C++/Python等)

    原文来自于:http://www.cnblogs.com/zhuyp1015/archive/2012/06/16/2552269.html 使用gvim在windows环境下搭建简单的IDE环境可以 ...

  4. Tautology

    WFF 'N PROOF is a logic game played with dice. Each die has six faces representing some subset of th ...

  5. 数据结构(虚树,动态规划):HNOI 2014 世界树

    Hnoi2014 世界树 Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平 ...

  6. 图论(二分图最大权独立点集):COGS 2051. 王者之剑

    2051. 王者之剑 ★★★☆   输入文件:Excalibur.in   输出文件:Excalibur.out   简单对比 时间限制:1 s   内存限制:256 MB [题目描述] 这是在阿尔托 ...

  7. 【宽搜】ECNA 2015 E Squawk Virus (Codeforces GYM 100825)

    题目链接: http://codeforces.com/gym/100825 题目大意: N个点M条无向边,(N<=100,M<=N(N-1)/2),起始感染源S,时间T(T<10) ...

  8. 数据结构——N皇后放置方法种数

    Description 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上. 你的任务是,对于给定的N,求出有多少种合 ...

  9. [AS/400] Control Language

    下面是一个简单的 CL 例子,转换日期格式:从 Julian 到 MDY,或者反方向转换. 接受两个参数,日期值 IN,目标类型 TYP,将转换后的日期值存入 OUT 中. PGM (&IN ...

  10. ubuntu12编译openwrt

    搭建编译环境 Ubuntu x64 12.04下的命令: sudo apt-get install subversion sudo apt-get install git sudo apt-get i ...