您的位置:首页 > 移动开发 > Android开发

android视图学习---Andriod的图形系统

2016-04-05 22:35 597 查看
什么是surfaceview?和surface有区别吗?SurfaceHolder和他们的关系是怎样?

知乎回答:http://www.zhihu.com/question/30922650

SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface。

你可以控制这个Surface的格式和尺寸。

Surfaceview控制这个Surface的绘制位置。



surface(其实可以理解就是一个显存)是纵深排序(Z-ordered)的,这表明它总在自己所在窗口的后面。


surfaceview提供了一个可见区域,只有在这个可见区域内
的surface部分内容才可见,可见区域外的部分不可见。


surface的排版显示受到视图层级关系的影响,它的兄弟视图结点会在顶端显示。

这意味者
surface的内容会被它的兄弟视图遮挡,这一特性可以用来放置遮盖物(overlays)(例如,文本和按钮等控件)。


注意,如果surface上面
有透明控件,那么它的每次变化都会引起框架重新计算它和顶层控件的透明效果,这会影响性能。




你可以通过SurfaceHolder接口访问这个surface,getHolder()方法可以得到这个接口。




surfaceview变得可见时,surface被创建;surfaceview隐藏前,surface被销毁。


这样能节省资源。如果你要查看
surface被创建和销毁的时机,可以重载surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)。



Canvas是Java层构建的数据结构,是给View用的画布。

ViewGroup会把自己的Canvas拆分给子View。

View会在onDraw方法里将图形数据绘制在它获得的Canvas上。

而Surface是Native层构建的数据结构,是给SurfaceFlinger用的画布。


它是直接被用来绘制到屏幕上的数据结构。

开发者一般所用的View都是在Canvas进行绘制,然后最顶层的View(通常是DecorView)的Canvas的数据信息会转换到一个Surface上。


SurfaceFlinger会将各个应用窗口的Surface进行合成,然后绘制到屏幕上(实际上是一个Buffer,但一般开发者不用考虑这些,所以省略一些概念)。

那为什么会有一个SurfaceView呢?

这是因为View的测量(Measure),布局(Layout)以及绘制(Draw)的计算量比较大。


计算完以后再从Canvas转换成Surface中数据,然后再绘制屏幕,这个流程比较耗时。

对于常规的UI绘制不会有什么问题,但是像Camera的预览以及视频的播放这样的应用场景来说就不可接受了。

因为Android限制了UI操作只能在主线程中。

所以像游戏、视频播放这些绘制任务比较繁重,为了不堵塞主线程就需要用SurfaceView,

它拥有自己的一个Surface,而因为是多线程的,只能让一个人在上面画,要是所有人都在同时画那岂不是乱套了

,所以需要用lockCanvas来锁住,等画完再unlock。



SurfaceView就是为了解决这个问题。


SurfaceView内容不再是绘制在Canvas上,而是直接绘制在其持有的一个Surface上。

由于省去了很多步骤,其绘制性能大大提高。

而SurfaceView本身只是用来控制这个Surface的大小和位置而已。

SurfaceView是在什么时候创建?

这个分两种情况,如果是在Xml布局文件里指定的那么就是随着Activity(这个可以想象成一个窗口页面)一起创建。

或者在代码运行到一定时间再创建。

而SurfaceView一开始创建出来后,它拥有的Surface不一定会一起创建出来,Surface有自己的生命周期,要等到SurfaceView可见时才正在创建,所以需要在Holder中设置一个Callback来让Surface状态变化时回调,这样我们就知道Surface当前状态是被创建了,还是已经被销毁了。被创建了表示可以开始准备绘制了,而被销毁后我们要释放其他资源。

SurfaceView是View的子类,它继承了View的特性,因此它能够叠加在其它的视图中。但是它又有着与其它视图不一样的特性,即它里面镶嵌了一个Surface。该Surface一般在包含SurfacevView的窗口后面,就好像surfaceview有个洞能够让该surface显露出来。
Surfaceview一般会继承SurfaceHolder的Callback接口。这样当SurfaceView创建时,就可以在该接口的三个方法里做相应的操作了,这三个方法其实就可以理解为SurfaceView中的surface的生命周期。

GLSurfaceView是SurfaceView的子类,它继承了Surfaceview的全部特性。 只不过,GLSurfaceView有个GLthread能够允许我们其上的Surface进行独立渲染视图。通过Renderer接口,我们可以调用opengl做自己的渲染。之后GLSurfaceView通过setRenderer方法启动GLthread线程

Camera, MediaPlayer和SurfaceView, GLSurfaceView:

Camera和MediaPlayler都可以理解为视频流的生产者。 它们都分别支持在SurfaceView和GLSurfaceView上显示视频流,明确的说是在它们的Surface上显示。先说Camera

Camera通过startPreview能够产生预览的每一帧。 它有一个方法setPreviewTexture,该方法是将预览和一个纹理(SurfaceTexture)绑定在一起,这样Camera每产生一张预览都会将其传给纹理,opengl有了该纹理后就能将其渲染在Surface上了。

同样,它也有一个setPreviewDisplay方法,该方法接收Surfaceview的holder,这样camera每产生一次预览都会直接通过holder显示在surface上。

再说MediaPlayer。 MediaPlayer在调用prepare方法之前需要先设置一个显示的窗口。通过setdisplay方法,它能与holder绑定在一块,这样MediaPlayer播放时,会显示在SurfaceView的窗口之上。

它也有一个setSurface的方法,通过在GLSurfaceView的Renderer接口方法onSurfaceCreated中,创建一个与SurfaceTexture绑定的Surface。之后,在MediaPlayer播放prepare之前,设置该surface。就能通过opengl渲染播放了。

至此,关于这些与SurfaceView有关的概念就介绍完毕了。

关于多媒体播放这一块,感兴趣的同学可以关注google4.4源码,的media/cts案例。

关于glsurfaceview感兴趣的可以关注google的grafika项目。

看完了之后,再回答上面的问题:


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

http://www.linuxidc.com/Linux/2012-08/67619.htm 这篇文章带我们从源码的角度来理解他们的关系

1、Surface

Surface

extends Object

implements Parcelable
java.lang.Object
Android.view.Surface

Class Overview

Handle onto a raw buffer that is being managed by the screen compositor.

简单翻译:

Surface是原始图像缓冲区(raw buffer)的一个句柄,而原始图像缓冲区是由屏幕图像合成器(screen compositor)管理的。

1.1、 就如在C语言编程一样,通过一个文件的句柄,就可以操作文件,获取文件的内容。 同样的,通过Surface就可以获取raw buffer其中的内容。原生缓冲区(raw buffer)存储着当前窗口的像素数据。

1.2、事实上,当得到一个Surface对象时,同时会得到一个Canvas(画布)对象。这一点可以通过查看\frameworks\base\core\java\android\view\Surface.java文件可知道Surface类定义了一个Canvas成员变量

//@\frameworks\base\core\java\android\view\Surface.java
// The mSurfaceControl will only be present for Surfaces used by the window
// server or system processes. When this class is parceled we defer to the
// mSurfaceControl to do the parceling. Otherwise we parcel the
// mNativeSurface.
private int mSurfaceControl;
private int mSaveCount;
private Canvas mCanvas;
private int mNativeSurface;
private int mSurfaceGenerationId;
private String mName;

1.3、 理解Canvas对象,可以把它当做画布,Canvas的方法大多数是设置画布的大小、形状、画布背景颜色等等,要想在画布上面画画,一般要与Paint对象结合使用,顾名思义,Paint就是画笔的风格,颜料的色彩之类的。

// 创建画笔
Paint paint = new Paint();
paint.setColor(Color.RED);// 设置红色

canvas.drawCircle(60, 20, 10, paint);// 画一个圆

1.4、Surface本身的作用类似一个句柄,得到了这个句柄就可以得到其中的Canvas、原生缓冲器以及其它方面的内容。

1.5、Surface实现了Parcelable接口,(implements Parcelable),也就是说Surface对象可以把显示内容的数据写入到 Parcel 中,并且能够从Parcel读回数据。

Parcelable

android.os.Parcelable


Known
Indirect Subclasses

AbsSavedState,AbsoluteSizeSpan,AccessibilityEvent,AccessibilityNodeInfo,AccessibilityServiceInfo,Account,AccountAuthenticatorResponse,ActivityInfo,ActivityManager.MemoryInfo,ActivityManager.ProcessErrorStateInfo,ActivityManager.RecentTaskInfo,ActivityManager.RunningAppProcessInfo,ActivityManager.RunningServiceInfo, ActivityManager.RunningTaskInfo,
and 144 others.

Class Overview

Interface for classes whose instances can be written to and restored from a
Parcel
.
Classes implementing the Parcelable interface must also have a static field called
CREATOR
, which is an object implementing the
Parcelable.Creator
interface.

简单翻译:

实现这个接口的对象可以写入数据到Parcel,同时也可以把数据读出来。

2、SurfaceView

SurfaceView

extends View

java.lang.Object
android.view.View
android.view.SurfaceView


Known
Direct Subclasses

GLSurfaceView,RSSurfaceView,VideoView

Class Overview

Provides a dedicated drawing surface embedded inside of a view hierarchy. You can control the format of this surface and, if you like, its size; the SurfaceView takes care of placing the surface at the correct location on the screen

The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings
of the SurfaceView that would normally appear on top of it. This can be used to place overlays such as buttons on top of the Surface, though note however that it can have an impact on performance since a full alpha-blended composite will be performed each
time the Surface changes.

Access to the underlying surface is provided via the SurfaceHolder interface, which can be retrieved by calling
getHolder()
.

The Surface will be created for you while the SurfaceView's window is visible; you should implement
surfaceCreated(SurfaceHolder)
and
surfaceDestroyed(SurfaceHolder)
to
discover when the Surface is created and destroyed as the window is shown and hidden.

One of the purposes of this class is to provide a surface in which a secondary thread can render into the screen. If you are going to use it this way, you need to be aware of some threading semantics:

All SurfaceView and
SurfaceHolder.Callback
methods
will be called from the thread running the SurfaceView's window (typically the main thread of the application). They thus need to correctly synchronize with any state that is also touched by the drawing thread.
You must ensure that the drawing thread only touches the underlying Surface while it is valid -- between
SurfaceHolder.Callback.surfaceCreated()
and
SurfaceHolder.Callback.surfaceDestroyed()
.

简单翻译:

SurfaceView提供了一个专门用于绘制的surface,这个surface内嵌于。你可以控制这个Surface的格式和尺寸。Surfaceview控制这个Surface在屏幕的正确绘制位置。

surface是Z-ordered的(也就是说在xyz坐标系中,按照Z坐标排序的,Z值大的表面覆盖在Z值小的表面的上方),这表明它总在自己所在窗口的后面。surfaceview在显示窗口处为Surface提供了一个可见区域,通过这个区域,才能看到Surface里面的内容。可以放置一些覆盖图层(overlays)在Surface上面,如Button、Textview之类的。但是,需要注意的是,如果Surface上面有全透明的控件,那么随着Surface的每一次变化,这些全透明的控件就会重新渲染,这样的话,就影响性能与显示的效果。

你可以通过SurfaceHolder这个接口去访问Surface,而执行getHolder()方法可以得到SurfaceHolder接口。

当SurfaceView的窗口可见时,Surface就会被创建,当SurfaceView窗口隐藏时,Surface就会被销毁。当然了,你也可以通过复写
surfaceCreated(SurfaceHolder)
surfaceDestroyed(SurfaceHolder)

这两个方法来验证一下Surface何时被创建与何时被销毁。

SurfaceView提供了一个运行在渲染线程的surface,若你要更新屏幕,你需要了解以下线程知识。

所有SurfaceView 和
SurfaceHolder.Callback
的方法都应该在主线程(UI线程)里面调用,应该要确保渲染进程所访问变量的同步性。
你必须确保只有当Surface有效的时候,(也就是当Surface的生命周期在
SurfaceHolder.Callback.surfaceCreated()
SurfaceHolder.Callback.surfaceDestroyed()
之间)才能让渲染进程访问。

2.1、SurfaceView与Surface的联系

简单来说,SurfaceView与Surface的联系就是,Surface是管理显示内容的数据(implementsParcelable),包括存储于数据的交换。而SurfaceView就是把这些数据显示出来到屏幕上面。

两者联系如图所示:



3、SurfaceHolder

SurfaceHolder

Android.view.SurfaceHolder

Class Overview

Abstract interface to someone holding a display surface. Allows you to control the surface size and format, edit the pixels in the surface, and monitor changes to the surface. This interface is typically available through the
SurfaceView
class.

When using this interface from a thread other than the one running its
SurfaceView
,
you will want to carefully read the methods
lockCanvas()
and
Callback.surfaceCreated()
.

简单翻译:

SurfaceHolder是控制surface的一个抽象接口,你可以通过SurfaceHolder来控制surface的尺寸和格式,或者修改surface的像素,监视surface的变化等等,SurfaceHolder是SurfaceView的典型接口。

与直接控制SurfaceView来修改surface不同,使用SurfaceHolder来修改surface时,需要注意
lockCanvas()
Callback.surfaceCreated()
.这两个方法。

SurfaceHolder控制surface的流程所使用的几个方法。

3.1、abstract void addCallback(SurfaceHolder.Callback callback)

Add a Callback interface for this holder.// 给SurfaceHolder一个回调对象。

3.2、abstract Canvas lockCanvas(Rect dirty)

Just like lockCanvas() but allows specification of a dirty rectangle.

// 锁定画布中的某一个区域,返回的画布对象Canvas(当更新的内容只有一个区域时,同时要追求高效,可以只更

新一部分的区域,而不必更新全部画布区域)

3.3、abstract Canvas lockCanvas()

Start editing the pixels in the surface.// 锁定画布,返回的画布对象Canvas

3.4、abstract void removeCallback(SurfaceHolder.Callback callback)

Removes a previously added Callback interface from this holder.//移除回调对象

3.5、abstract void unlockCanvasAndPost(Canvas canvas)

Finish editing pixels in the surface.// 结束锁定画图,并提交改变。
4、SurfaceHolder.Callback

SurfaceHolder.Callback

android.view.SurfaceHolder.Callback


Known
Indirect Subclasses

GLSurfaceView,NativeActivity,RSSurfaceView,SurfaceHolder.Callback2

Class Overview

A client may implement this interface to receive information about changes to the surface. When used with a
SurfaceView
,
the Surface being held is only available between calls to
surfaceCreated(SurfaceHolder)
and
surfaceDestroyed(SurfaceHolder)
.
The Callback is set with
SurfaceHolder.addCallback
method.

简单翻译:

SurfaceHolder.Callback是监听surface改变的一个接口

4.1、public abstract voidsurfaceChanged(SurfaceHolder holder,
int format, int width, int height)

holderThe SurfaceHolder whose surface has changed.
formatThe new PixelFormat of the surface.
widthThe new width of the surface.
heightThe new height of the surfa
//surface发生改变时被调用

4.2、public abstract voidsurfaceCreated(SurfaceHolder holder)

Parameters
holderThe SurfaceHolder whose surface is being created
//在surface创建时被调用,一般在这个方法里面开启渲染屏幕的线程。


4.3、public abstract voidsurfaceDestroyed(SurfaceHolder holder)


Parameters

holderThe SurfaceHolder whose surface is being destroyed.
//销毁时被调用,一般在这个方法里将渲染的线程停止。

附上上述所说几种的联系方法

SurfaceHolder = SurfaceView.getHolder();

Surface = SurfaceHolder.getSurface();

Canvas =SurfaceHolder.LockCanvas(Rect dirty)

Canvas =Surface.lockCanvas(Rect dirty)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: