SurfaceView与TextureView详解
在Android开发中,我们经常会遇到需要在屏幕上绘制自定义图形或者实现高性能的实时渲染场景,这时,我们就需要使用到SurfaceView和TextureView这两个重要的组件,本文将详细介绍SurfaceView和TextureView的原理、使用方法以及相关问题解答。
SurfaceView
1、1 原理
SurfaceView是Android 3.0(API级别11)引入的一个新组件,它是一个视图,用于在其上绘制应用程序的内容,SurfaceView的主要作用是提供一个绘图表面,让我们可以在上面进行绘制操作,SurfaceView继承自View,因此可以使用所有的视图方法。
1、2 使用方法
创建一个SurfaceView实例,并重写其onDraw方法,在其中进行绘制操作。
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Canvas mCanvas; public MySurfaceView(Context context) { super(context); mHolder = getHolder(); mHolder.addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { mCanvas = holder.lockCanvas(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (mCanvas != null) { holder.unlockCanvasAndPost(mCanvas); } } @Override public void onDraw(Canvas canvas) { // 在此处进行绘制操作 } }
1、3 性能优化
为了提高SurfaceView的性能,我们可以采用双缓冲技术,双缓冲技术的基本原理是,我们在内存中创建一个与屏幕缓冲区大小相同的缓冲区,然后在这个缓冲区上进行绘制操作,这样,当系统需要交换缓冲区时,只需要交换内存中的缓冲区和屏幕缓冲区,而不需要直接操作屏幕缓冲区,从而减少了系统调用的开销,具体实现如下:
private void initBuffers() { int width = getWidth(); int height = getHeight(); int stride = Math.max(width, height) * 4; // 每个像素4个字节(RGBA) ByteBuffer[] buffers = new ByteBuffer[2]; int[] formats = new int[]{PixelFormat.RGBA_8888}; mBackBuffer = ByteBuffer.allocateDirect(stride * height); mBackBuffer.order(ByteOrder.nativeOrder()); mBackBuffer.asIntBuffer().put(new int[]{0xff000000, 0xff000000, 0xff000000, 0xff}); // Alpha值全为255,表示完全不透明 mFrontBuffer = mBackBuffer; // mFrontBuffer和mBackBuffer共享数据,互换位置时不会丢失数据 mFrontBuffer.position(0); // 将mFrontBuffer的数据指针移动到起始位置,以便后续操作 mFrontBuffer.limit(stride * height); // 将mFrontBuffer的数据界限设置为整个缓冲区的容量,以便后续操作 mOffscreenBitmap = Bitmap.createBitmap(width, height, formats[0], mBackBuffer, mFrontBuffer); // 根据格式、宽度、高度、源缓冲区和目标缓冲区创建位图对象 }
TextureView
2、1 原理
TextureView是Android N(API级别24)引入的一个新组件,它是一个视图,用于在其上显示视频或纹理内容,TextureView的主要作用是提供一个纹理表面,让我们可以在上面绘制视频帧或者显示纹理图片,TextureView继承自ImageView,因此可以使用所有的图像处理方法,TextureView还支持硬件加速,可以大大提高视频播放的性能。
2、2 使用方法
创建一个TextureView实例,并重写其onDraw方法,在其中进行绘制操作。
public class MyTextureView extends TextureView implements SurfaceTextureListener { private SurfaceTexture mSurfaceTexture; private Surface mSurface; private EGLContext mEGLContext; private EGLDisplay mEGLDisplay; private EGLSurface mEGLSurface; private GLSurfaceView mGLSurfaceView; public MyTextureView(Context context) { super(context); setSurfaceTextureListener(this); // 为TextureView设置监听器,以便在surface创建时获取surfaceTexture对象并进行初始化操作 } @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { mSurfaceTexture = surfaceTexture; // 将surfaceTexture对象保存到成员变量中,以便后续操作 initEGL(); // 对EGL进行初始化操作,包括获取EGLDisplay、EGLContext和EGLSurface等资源对象 openGLSurface(); // 将OpenGL ES渲染上下文关联到EGLSurface上,并启动渲染线程进行渲染操作,如果成功关联,则会自动调用onDrawFrame方法进行绘制操作,否则,需要在onDrawFrame方法中手动绘制,关闭OpenGL ES渲染上下文和相关资源。
原创文章,作者:K-seo,如若转载,请注明出处:https://www.kdun.cn/ask/137486.html