`

SurfaceView和View最本质的区别

阅读更多
在Android游戏当中充当主要的除了控制类外就是显示类,在J2ME中我们用Display和Canvas来实现这些,而Google Android中涉及到显示的为view类,Android游戏开发中比较重要和复杂的就是显示和游戏逻辑的处理。
这里我们说下android.view.View和android.view.SurfaceView。SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用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构建,同时Android123未来后面说到的OpenGL中的GLSurfaceView也是从该类实现。


SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。
那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。
当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。

所以基于以上,根据游戏特点,一般分成两类。

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

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

下面是使用sufaceView一个基本的框架:
package com.ql.app;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class TestSurfaceView extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));
    }
    
    class MyView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
    	SurfaceHolder holder=null;
    	Paint paint;
		public MyView(Context context) {
			super(context);
			// TODO Auto-generated constructor stub
			holder=getHolder();
			holder.addCallback(this);
			paint=new Paint(Paint.ANTI_ALIAS_FLAG);
			paint.setColor(Color.RED);
			
			this.setFocusable(true);
		}

		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			// TODO Auto-generated method stub
			Thread t=new Thread(this);
			t.start();
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			// TODO Auto-generated method stub
			isRunning=false;
		}

		@Override
		protected void onDraw(Canvas canvas) {
			// TODO Auto-generated method stub
			canvas=holder.lockCanvas();
			//刷屏  
	        canvas.drawColor(Color.BLACK);
	        
			canvas.drawCircle(x, y, 10, paint);
			
			holder.unlockCanvasAndPost(canvas);
		}
		private void paint(Paint paint) {
			Canvas canvas=holder.lockCanvas();
			//刷屏  
	        canvas.drawColor(Color.BLACK);
	        
			canvas.drawCircle(x, y, 10, paint);
			
			holder.unlockCanvasAndPost(canvas);
		}
		
		boolean isRunning=true;
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while (isRunning) {
//				onDraw(null);
				paint(paint);
				move();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}
    	
		private int x,y;
		private void move(){
			x+=2;
			y+=2;
		}
    }
    
}

分享到:
评论
2 楼 xzongyuan 2013-05-14  
分析的很详尽,精彩
1 楼 George_ghc 2012-06-04  
嗯不错!学习

相关推荐

    学习SurfaceView

    - **游戏动画**:对于复杂的游戏动画,SurfaceView能够提供更高的帧率和更流畅的用户体验,尤其是在需要大量图形处理的情况下。 - **多媒体应用**:SurfaceView还可以用于开发其他类型的多媒体应用,如视频会议、...

    Android视频裁剪 - 含裁剪View

    4. **绘制裁剪框**:在View的`onDraw()`方法中,根据裁剪区域的坐标和大小绘制裁剪框。 5. **交互反馈**:提供适当的视觉反馈,如边框高亮、拖动动画等,提升用户体验。 四、使用第三方库 Android社区提供了很多...

    Android手机游戏开发知识点总结.pdf

    首先,游戏的本质是一个状态机,它不断地在View或SurfaceView上绘制内容,同时响应用户的输入事件。在Android开发中,通常采用MVC(Model-View-Controller)模式来组织代码。 1. **View和SurfaceView**:这两个类是...

    仿咻一咻地震波效果

    1. **基础组件**:在Android中,我们可以使用`View`或者`SurfaceView`作为载体来绘制和更新动画。`View`适合在主线程中进行简单的绘图,而`SurfaceView`则适合处理复杂的图形和动画,因为它提供了独立于主线程的渲染...

    Android中高级面试必知必会.pdf

    - **SurfaceView、TextureView、GLSurfaceView区别**:适用于不同场景下的View选择,例如在复杂图形渲染时使用GLSurfaceView。 #### 架构和组件 - **MVC、MVP、MVVM**:三种常用的软件架构模式,它们各自有不同的...

    android平台中使用j2me MIDP2.0中GameAPI

    总结,Android平台上的游戏开发虽然与J2ME MIDP 2.0的Game API有本质区别,但通过合理的移植和重构,可以复用部分代码和设计理念。开发者需要理解Android的绘图机制和事件处理模型,以便将MIDP 2.0的Game API有效地...

    自定义 折线图

    自定义折线图的第一步是创建一个自定义的View类,继承自View或者SurfaceView。在这个类中,我们将重写`onDraw()`方法,这是进行图形绘制的主要入口。 2. **准备数据** 在实现折线图之前,你需要有一组数据来描绘...

    surfaceViewPlayVideo:surfaceViewPlayVideo示例

    `SurfaceView`与普通的`View`不同,它的本质是一个窗口,直接与系统的硬件层交互,因此在处理视频流时,能提供更流畅的体验,避免UI阻塞。 `SurfaceView`的主要特点包括: 1. **双缓冲**:`SurfaceView`具有后台...

    android简易画图工具

    在Android中,我们可以使用`Canvas`类来进行图形绘制,它是`View`或`SurfaceView`的子类的核心组件。开发者通常会创建一个自定义的`View`类,重写`onDraw()`方法,该方法会在每次视图需要更新时被调用。在这个方法中...

    详解Android 折叠屏适配攻略

    折叠屏适配的本质是:当应用程序运行时,屏幕的尺寸、密度或比例发生了变化,应用程序能够继续在变化后的屏幕上正常显示和正常运行。 android:resizeableActivity 属性 要适配折叠屏,首先是要让应用程序支持动态...

Global site tag (gtag.js) - Google Analytics