Android之SurfaceView学习

首先我们先来看下官方API对SurfaceView的介绍

SurfaceView的API介绍

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 in to 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是视图(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)。
surfaceview的核心在于提供了两个线程:UI线程和渲染线程。这里应注意:
1> 所有SurfaceView和SurfaceHolder.Callback的方法都应该在UI线程里调用,一般来说就是应用程序主线程。渲染线程所要访问的各种变量应该作同步处理。
2> 由于surface可能被销毁,它只在SurfaceHolder.Callback.surfaceCreated()和 SurfaceHolder.Callback.surfaceDestroyed()之间有效,所以要确保渲染线程访问的是合法有效的surface。

接下来呢,说说自己对它的理解
1、定义

可以直接从内存或者DMA等硬件接口取得图像数据,是个非常重要的绘图容器。

它的特性是:可以在主线程之外的线程中向屏幕绘图上。这样可以避免画图任务繁重的时候造成主线程阻塞,从而提高了程序的反应速度。在游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等等尽量在画布canvas中画出。

2、实现

首先继承SurfaceView并实现SurfaceHolder.Callback接口
使用接口的原因:因为使用SurfaceView 有一个原则,所有的绘图工作必须得在Surface 被创建之后才能开始(Surface—表面,这个概念在 图形编程中常常被提到。基本上我们可以把它当作显存的一个映射,写入到Surface 的内容
可以被直接复制到显存从而显示出来,这使得显示速度会非常快),而在Surface 被销毁之前必须结束。所以Callback 中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界。

需要重写的方法

 (1)public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}

  //在surface的大小发生改变时激发

 (2)public void surfaceCreated(SurfaceHolder holder){}

  //在创建时激发,一般在这里调用画图的线程。

 (3)public void surfaceDestroyed(SurfaceHolder holder) {}

  //销毁时激发,一般在这里将画图的线程停止、释放。

整个过程:继承SurfaceView并实现SurfaceHolder.Callback接口 ----> SurfaceView.getHolder()获得SurfaceHolder对象 ---->SurfaceHolder.addCallback(callback)添加回调函数---->SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布----> Canvas绘画 ---->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。

3、SurfaceHolder
这里用到了一个类SurfaceHolder,可以把它当成surface的控制器,用来操纵surface。处理它的Canvas上画的效果和动画,控制表面,大小,像素等。
几个需要注意的方法:
(1)、abstract void addCallback(SurfaceHolder.Callback callback);
// 给SurfaceView当前的持有者一个回调对象。
(2)、abstract Canvas lockCanvas();
// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
(3)、abstract Canvas lockCanvas(Rect dirty);
// 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。
// 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。
(4)、abstract void unlockCanvasAndPost(Canvas canvas);
// 结束锁定画图,并提交改变。
4、实例

这里的例子实现了一个矩形和一个计时器



1
package
xl.test;

2

3

import
android.app.Activity;

4

import
android.content.Context;

5

import
android.graphics.Canvas;

6

import
android.graphics.Color;

7

import
android.graphics.Paint;

8

import
android.graphics.Rect;

9

import
android.os.Bundle;

10

import
android.view.SurfaceHolder;

11

import
android.view.SurfaceView;

12

13

public

class
ViewTest
extends
Activity {

14

/**
Called when the activity is first created.
*/

15
@Override

16

public

void
onCreate(Bundle savedInstanceState) {

17

super
.onCreate(savedInstanceState);

18
setContentView(
new
MyView(
this
));

19
}

20

//
视图内部类

21

class
MyView
extends
SurfaceView
implements
SurfaceHolder.Callback

22
{

23

private
SurfaceHolder holder;

24

private
MyThread myThread;

25

public
MyView(Context context) {

26

super
(context);

27

//
TODO Auto-generated constructor stub

28

holder
=

this
.getHolder();

29
holder.addCallback(
this
);

30
myThread
=

new
MyThread(holder);
//
创建一个绘图线程

31

}

32

33
@Override

34

public

void
surfaceChanged(SurfaceHolder holder,
int
format,
int
width,

35

int
height) {

36

//
TODO Auto-generated method stub

37

38
}

39

40
@Override

41

public

void
surfaceCreated(SurfaceHolder holder) {

42

//
TODO Auto-generated method stub

43

myThread.isRun
=

true
;

44
myThread.start();

45
}

46

47
@Override

48

public

void
surfaceDestroyed(SurfaceHolder holder) {

49

//
TODO Auto-generated method stub

50

myThread.isRun
=

false
;

51
}

52

53
}

54

//
线程内部类

55

class
MyThread
extends
Thread

56
{

57

private
SurfaceHolder holder;

58

public

boolean
isRun ;

59

public
MyThread(SurfaceHolder holder)

60
{

61

this
.holder
=
holder;

62
isRun
=

true
;

63
}

64
@Override

65

public

void
run()

66
{

67

int
count
=

0
;

68

while
(isRun)

69
{

70
Canvas c
=

null
;

71

try

72
{

73

synchronized
(holder)

74
{

75
c
=
holder.lockCanvas();
//
锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。

76

c.drawColor(Color.BLACK);
//
设置画布背景颜色

77

Paint p
=

new
Paint();
//
创建画笔

78

p.setColor(Color.WHITE);

79
Rect r
=

new
Rect(
100
,
50
,
300
,
250
);

80
c.drawRect(r, p);

81
c.drawText(
"
这是第
"
+
(count
++
)
+
"

"
,
100
,
310
, p);

82
Thread.sleep(
1000
);
//
睡眠时间为1秒

83

}

84
}

85

catch
(Exception e) {

86

//
TODO: handle exception

87

e.printStackTrace();

88
}

89

finally

90
{

91

if
(c
!=

null
)

92
{

93
holder.unlockCanvasAndPost(c);
//
结束锁定画图,并提交改变。

94

95
}

96
}

97
}

98
}

99
}

100
}

时间: 2024-10-26 06:08:47

Android之SurfaceView学习的相关文章

Android之SurfaceView学习(一)转转

Android之SurfaceView学习(一) 首先我们先来看下官方API对SurfaceView的介绍 SurfaceView的API介绍 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 pla

Android之SurfaceView学习(一)

首先我们先来看下官方API对SurfaceView的介绍 SurfaceView的API介绍 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 c

[Android游戏开发学习笔记]View和SurfaceView

本文为阅读http://blog.csdn.net/xiaominghimi/article/details/6089594的笔记. 在Android游戏中充当主要角色的,除了控制类就是显示类.而在Android中涉及到显示的是View类,及继承自它的SurfaceView类和SurfaceView的其他子类等. 这里先只说View和SurfaceView.SurfaceView的直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及CAmera摄像头一般均使用Su

Android视图SurfaceView的实现原理分析

附:Android控件TextView的实现原理分析 来源:http://blog.csdn.net/luoshengyang/article/details/8661317 在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面.由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制.又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输

android开发的学习路线

android开发的学习路线 第一阶段:Java面向对象编程1.Java基本数据类型与表达 式,分支循环. 2.String和StringBuffer的使用.正则表达式. 3.面向对象的抽象,封装,继承,多态,类与对象,对象初始化和回 收:构造函数.this关键字.方法和方法的参数传递过程.static关键字.内部类,Java的垃极回收机制,Javadoc介绍. 4.对象实例化 过程.方法的覆盖.final关键字.抽象类.接口.继承的优点和缺点剖析:对象的多态性:子类和父类之间的转换.抽象类和接

Android 零基础学习之路

第一阶段:Java面向对象编程 1.Java基本数据类型与表达式,分支循环. 2.String和StringBuffer的使用.正则表达式. 3.面向对象的抽象,封装,继承,多态,类与对象,对象初始化和回收:构造函数.this关键字.方法和方法的参数传递过程.static关键字.内部类,Java的垃极回收机制,Javadoc介绍. 4.对象实例化过程.方法的覆盖.final关键字.抽象类.接口.继承的优点和缺点剖析:对象的多态性:子类和父类之间的转换.抽象类和接口在多态中的应用.多态带来的好处.

Android直播推流学习

Android直播推流学习 Android直播推流学习 第一部 第二部 第三部 第四部 第一部 本文也主要是一步步分析spydroid源码. 首先spydroid的采用的协议是RTSP,目前我知道支持RTSP协议的服务器是Darwin,但是Darwin比较复杂,所以大家可以选择EasyDarwin,大家可以去搜搜看看.还是继续说spydroid吧,spydroid这个项目大家可以在github上搜到的,不过作者也是很久没有更新了,如果大家只做推流的话可以看看原作者的另外一个项目Spydroid.

基于 Android NDK 的学习之旅----- C调用Java

http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html 基于 Android NDK 的学习之旅----- C调用Java许多成熟的C引擎要移植到Android 平台上使用 , 一般都会 提供 一些接口, 让Android sdk 和 jdk 实现. 下文将会介绍 C 如何 通过 JNI 层调用 Java 的静态和非静态方法. 1.主要流程 1.  新建一个测试类TestProvider.java a)       

【转】基于 Android NDK 的学习之旅-----数据传输(引用数据类型)

原文网址:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/20/2147086.html 基于 Android NDK 的学习之旅-----数据传输二(引用数据类型)(附源码) 基于 Android NDK 的学习之旅-----数据传输(引用数据类型) 接着上篇文章继续讲.主要关于引用类型的数据传输,本文将介绍字符串传输和自定义对象的传输. 1.主要流程 1.  String 字符串传输 a)         上层定义一个native的方法