android 中View SurfaceView SurfaceTexture 的区别
来源:互联网 发布:高铁抢票软件 编辑:程序博客网 时间:2024/06/05 15:21
Android SurfaceView 与 View 的区别:
http://bbs.51cto.com/thread-965972-1.html
如果你的游戏不吃CPU,用View就比较好,符合标准Android操作方式,由系统决定刷新surface的时机。
但如果很不幸的,你做不到不让你的程序吃CPU,你就只好使用SurfaceView来强制刷新surface了,不然系统的UI进程很可能抢不过你那些吃CPU的线程。
当然其实不止这两种方法来刷新Surface的,这两种只是纯Java应用比较常见的方法。
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来控制。
一般2D游戏开发使用SurfaceView足够,因为它也是google专们扩展用于2D游戏开发的画布
使用普通的游戏画布(Android中2D专用游戏画布)中进行绘制图片,然后在GLSurfaceView(Android中3D游戏专用画布)中渲染图片的对比中发现GLSurfaceView的效率高于SurfaceView的30倍;GLSurfaceView的效率主要是因为机器硬件的GPU加速,现在flash技术也有了GPU加速技术;
下面总结一下:
一般2D游戏使用SurfaceView足够,所以不要认为什么都要使用GLSurfaceView(openGL),而且 GLSurfaceView的弊端在于适配能力差,因为很多机型中是没有GPU加速的。【这里总结的很好】
如果你的游戏不吃CPU,用View就比较好,符合标准Android操作方式,由系统决定刷新surface的时机。
但如果很不幸的,你做不到不让你的程序吃CPU,你就只好使用SurfaceView来强制刷新surface了,不然系统的UI进程很可能抢不过你那些吃CPU的线程。
当然其实不止这两种方法来刷新Surface的,这两种只是纯Java应用比较常见的方法。
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来控制。
一般2D游戏开发使用SurfaceView足够,因为它也是google专们扩展用于2D游戏开发的画布
使用普通的游戏画布(Android中2D专用游戏画布)中进行绘制图片,然后在GLSurfaceView(Android中3D游戏专用画布)中渲染图片的对比中发现GLSurfaceView的效率高于SurfaceView的30倍;GLSurfaceView的效率主要是因为机器硬件的GPU加速,现在flash技术也有了GPU加速技术;
下面总结一下:
一般2D游戏使用SurfaceView足够,所以不要认为什么都要使用GLSurfaceView(openGL),而且 GLSurfaceView的弊端在于适配能力差,因为很多机型中是没有GPU加速的。【这里总结的很好】
SurfaceTexture 与 SurfaceView 的区别:
http://www.cnblogs.com/hrlnw/p/3277300.html
SurfaceTexture是从Android3.0(API 11)加入的一个新类。这个类跟SurfaceView很像,可以从camera preview或者video decode里面获取图像流(image stream)。但是,和SurfaceView不同的是,SurfaceTexture在接收图像流之后,不需要显示出来。有做过Android camera开发的人都知道,比较头疼的一个问题就是,从camera读取到的预览(preview)图像流一定要输出到一个可见的(Visible)SurfaceView上,然后通过Camera.PreviewCallback的public void onPreviewFrame(byte[] data, Camera camera)函数来获得图像帧数据的拷贝。这就存在一个问题,比如我希望隐藏摄像头的预览图像或者对每一帧进行一些处理再显示到手机显示屏上,那么在Android3.0之前是没有办法做到的,或者说你需要用一些小技巧,比如用其他控件把SurfaceView给挡住,注意这个显示原始camera图像流的SurfaceView其实是依然存在的,也就是说被挡住的SurfaceView依然在接收从camera传过来的图像,而且一直按照一定帧率去刷新,这是消耗cpu的,而且如果一些参数设置的不恰当,后面隐藏的SurfaceView有可能会露出来,因此这些小技巧并不是好办法。但是,有了SurfaceTexture之后,就好办多了,因为SurfaceTexture不需要显示到屏幕上,因此我们可以用SurfaceTexture接收来自camera的图像流,然后从SurfaceTexture中取得图像帧的拷贝进行处理,处理完毕后再送给另一个SurfaceView用于显示即可。
SurfaceTexture是从Android3.0(API 11)加入的一个新类。这个类跟SurfaceView很像,可以从camera preview或者video decode里面获取图像流(image stream)。但是,和SurfaceView不同的是,SurfaceTexture在接收图像流之后,不需要显示出来。有做过Android camera开发的人都知道,比较头疼的一个问题就是,从camera读取到的预览(preview)图像流一定要输出到一个可见的(Visible)SurfaceView上,然后通过Camera.PreviewCallback的public void onPreviewFrame(byte[] data, Camera camera)函数来获得图像帧数据的拷贝。这就存在一个问题,比如我希望隐藏摄像头的预览图像或者对每一帧进行一些处理再显示到手机显示屏上,那么在Android3.0之前是没有办法做到的,或者说你需要用一些小技巧,比如用其他控件把SurfaceView给挡住,注意这个显示原始camera图像流的SurfaceView其实是依然存在的,也就是说被挡住的SurfaceView依然在接收从camera传过来的图像,而且一直按照一定帧率去刷新,这是消耗cpu的,而且如果一些参数设置的不恰当,后面隐藏的SurfaceView有可能会露出来,因此这些小技巧并不是好办法。但是,有了SurfaceTexture之后,就好办多了,因为SurfaceTexture不需要显示到屏幕上,因此我们可以用SurfaceTexture接收来自camera的图像流,然后从SurfaceTexture中取得图像帧的拷贝进行处理,处理完毕后再送给另一个SurfaceView用于显示即可。
在该应用场景中,我需要从camera读取图像流,然后对其处理,最后将处理结果显示到手机屏幕上。因此我写了一个GameDisplay类用于处理以上所有事务,而在MainActivity中,只需要创建一个GameDisplay类的实例并且初始化即可。
package com.song.camgame;import java.io.IOException;import java.util.List;import java.util.Timer;import java.util.TimerTask;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.ImageFormat;import android.graphics.Rect;import android.graphics.SurfaceTexture;import android.hardware.Camera;import android.hardware.Camera.Size;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;public class GameDisplay extends SurfaceView implements SurfaceHolder.Callback,Camera.PreviewCallback{ public final static String TAG="GameDisplay"; private static final int MAGIC_TEXTURE_ID = 10; public static final int DEFAULT_WIDTH=800; public static final int DEFAULT_HEIGHT=480; public static final int BLUR = 0; public static final int CLEAR = BLUR + 1; //public static final int PAUSE = PLAY + 1; //public static final int EXIT = PAUSE + 1; public SurfaceHolder gHolder; public SurfaceTexture gSurfaceTexture; public Camera gCamera; public byte gBuffer[]; public int textureBuffer[]; public ProcessThread gProcessThread; private int bufferSize; private Camera.Parameters parameters; public int previewWidth, previewHeight; public int screenWidth, screenHeight; public Bitmap gBitmap; private Rect gRect; // timer private Timer sampleTimer; private TimerTask sampleTask; public GameDisplay(Context context,int screenWidth,int screenHeight) { super(context); gHolder=this.getHolder(); gHolder.addCallback(this); gHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); gSurfaceTexture=new SurfaceTexture(MAGIC_TEXTURE_ID); this.screenWidth=screenWidth; this.screenHeight=screenHeight; gRect=new Rect(0,0,screenWidth,screenHeight); Log.v(TAG, "GameDisplay initialization completed"); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.v(TAG, "GameDisplay surfaceChanged"); parameters = gCamera.getParameters(); List<Size> preSize = parameters.getSupportedPreviewSizes(); previewWidth = preSize.get(0).width; previewHeight = preSize.get(0).height; for (int i = 1; i < preSize.size(); i++) { double similarity = Math .abs(((double) preSize.get(i).height / screenHeight) - ((double) preSize.get(i).width / screenWidth)); if (similarity < Math.abs(((double) previewHeight / screenHeight) - ((double) previewWidth / screenWidth))) { previewWidth = preSize.get(i).width; previewHeight = preSize.get(i).height; } } gBitmap= Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888); parameters.setPreviewSize(previewWidth, previewHeight); gCamera.setParameters(parameters); bufferSize = previewWidth * previewHeight; textureBuffer=new int[bufferSize]; bufferSize = bufferSize * ImageFormat.getBitsPerPixel(parameters.getPreviewFormat()) / 8; gBuffer = new byte[bufferSize]; gCamera.addCallbackBuffer(gBuffer); gCamera.setPreviewCallbackWithBuffer(this); gCamera.startPreview(); //gProcessThread = new ProcessThread(surfaceView,handler,null,previewWidth,previewHeight); //processThread.start(); } @Override public void surfaceCreated(SurfaceHolder holder) { Log.v(TAG, "GameDisplay surfaceCreated"); if (gCamera == null) { gCamera = Camera.open(); } gCamera.setPreviewTexture(gSurfaceTexture); //sampleStart(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.v(TAG, "GameDisplay surfaceDestroyed"); //gProcessThread.isRunning=false; //sampleTimer.cancel(); //sampleTimer = null; //sampleTask.cancel(); //sampleTask = null; gCamera.stopPreview(); gCamera.release(); } @Override public void onPreviewFrame(byte[] data, Camera camera) { Log.v(TAG, "GameDisplay onPreviewFrame"); //gProcessThread.raw_data=data; camera.addCallbackBuffer(gBuffer); for(int i=0;i<textureBuffer.length;i++) textureBuffer[i]=0xff000000|data[i]; gBitmap.setPixels(textureBuffer, 0, previewWidth, 0, 0, previewWidth, previewHeight); synchronized (gHolder) { Canvas canvas = this.getHolder().lockCanvas(); canvas.drawBitmap(gBitmap, null,gRect, null); //canvas.drawBitmap(textureBuffer, 0, screenWidth, 0, 0, screenWidth, screenHeight, false, null); this.getHolder().unlockCanvasAndPost(canvas); } } public void sampleStart() { Log.v(TAG, "GameDisplay sampleStart"); sampleTimer = new Timer(false); sampleTask = new TimerTask() { @Override public void run() { gProcessThread.timer=true; } }; sampleTimer.schedule(sampleTask,0, 80); }}以上程序中115-130行是最重要的部分,data是从SurfaceTexture获得的camera图像帧的拷贝,119-121行对其进行了简单的处理,122-128行将处理过的图像数据传递给负责显示的SurfaceView并显示出来。
MainActivity对GameDisplay的调用如下:
//声明private GameDisplay gameDisplay;//初始化gameDisplay.setVisibility(SurfaceView.VISIBLE);DisplayMetrics dm = getResources().getDisplayMetrics();screenWidth = dm.widthPixels;screenHeight = dm.heightPixels;gameDisplay= new GameDisplay(this,dm.widthPixels,dm.heightPixels);//加入到当前activity的layout中FrameLayout root = (FrameLayout) findViewById(R.id.root);root.addView(gameDisplay,0);
补充:
SurfaceView 与 SurfaceTexture 的区别还多了一条,SurfaceTexture 比 SurfaceView 更耗电。
0 0
- android 中View SurfaceView SurfaceTexture 的区别
- Android中view和surfaceview的区别
- Android中SurfaceView和View的区别
- Android中SurfaceView和View的区别
- Android中view和surfaceview的区别
- android中view surfaceView GLSurfaceView的区别
- Android中view和surfaceview的区别
- SurfaceView, TextureView, SurfaceTexture等的区别
- SurfaceTexture,TextureView, SurfaceView和GLSurfaceView的区别
- SurfaceView, TextureView, SurfaceTexture等的区别
- Android中View,SurfaceView和GLSurfaceView绘图的区别
- Android中View,SurfaceView和GLSurfaceView绘图的区别
- 实习杂记(33):surfaceTexture 和 surfaceview 的区别
- android中的surfaceview与surfacetexture
- Android SurfaceView和View的区别
- android View和SurfaceView的区别
- Android surfaceView 与View 的区别
- android SurfaceView和View的区别
- ubuntu15.04下Android studio开发配置完全教程
- Permutation Sequence (略)
- 配置Log4j(很详细)
- ActiveMQ安装部署(Windows)
- save()方法添加数据了,可是delete()和Update()方法总是没有效果
- android 中View SurfaceView SurfaceTexture 的区别
- 为什么写博客
- Java基础几问
- scala 参考文档
- 机器学习心得
- hdoj 5451 Best Solver 【求循环节 + 矩阵快速幂】
- 工厂方法模式
- 转Java并发包学习七]解密ThreadLocal
- centos5.x安装Mysql笔记