Android Surface详解

一、Surface的基本概念

Surface是Android系统中一个重要的原语,它是一块屏幕的抽象表示。它提供了一个支持绘制、更改尺寸、透明度、格式和管理SurfaceView的生命周期的接口。在Android应用程序中,Surface通常表示一个可以渲染、处理用户输入、与其他SurfaceView进行组合的视图元素。

在不同的场景下,Surface可以有不同的实现方式:SurfaceView、TextureView、GLSurfaceView等等。SurfaceView是其中应用最为广泛的一种实现方式,因为在面向用户的应用程序中,通过SurfaceView可以提供流畅的UI交互和动画效果。

二、SurfaceView的使用

SurfaceView是Android系统提供的一种底层视图,它可以用于自定义绘制以及更高效地渲染大量视图。

下面是一个简单的SurfaceView实现代码:

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    private Thread drawThread;
    private volatile boolean running = false;

    public MySurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        getHolder().addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        running = true;
        drawThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (running) {
                    draw();
                }
            }
        });
        drawThread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO: Implement surfaceChanged()
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        running = false;
        try {
            drawThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void draw() {
        SurfaceHolder holder = getHolder();
        Canvas canvas = holder.lockCanvas();
        if (canvas != null) {
            // 绘制
            holder.unlockCanvasAndPost(canvas);
        }
    }
}

在该实现中,我们重写了SurfaceView的三个生命周期方法,分别是surfaceCreated、surfaceChanged和surfaceDestroyed。在surfaceCreated中,我们创建了一个绘制线程,在循环中不断地调用draw()方法来进行绘制工作。在surfaceDestroyed中,我们停止了绘制线程,调用join()方法等待其结束。

三、SurfaceView的局限性

尽管SurfaceView提供了一个强大的绘制框架,但是在实际开发中,我们也要考虑到其局限性。在特定的场景下,SurfaceView可能会出现一些问题,例如:卡顿、闪烁、裂屏等等。

为了解决这些问题,我们可以采用一些优化手段,例如:

四、TextureView的使用

TextureView是Android系统提供的一种基于硬件加速的视图,它可以在不同Surface之间进行无缝切换,并且支持叠加和混合。在一些高级应用程序中,如果需要同时显示多个Surface,我们可以选择使用TextureView实现。

下面是一个简单的TextureView实现代码:

public class MyTextureView extends TextureView implements TextureView.SurfaceTextureListener {

    private Thread drawThread;
    private volatile boolean running = false;
    private SurfaceTexture surfaceTexture;

    public MyTextureView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setSurfaceTextureListener(this);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
        running = true;
        this.surfaceTexture = surfaceTexture;
        drawThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (running) {
                    draw();
                }
            }
        });
        drawThread.start();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
        // TODO: Implement onSurfaceTextureSizeChanged()
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        running = false;
        try {
            drawThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
        // TODO: Implement onSurfaceTextureUpdated()
    }

    private void draw() {
        if (surfaceTexture == null) {
            return;
        }
        Canvas canvas = lockCanvas();
        if (canvas != null) {
            // 绘制
            unlockCanvasAndPost(canvas);
        }
    }
}

在该实现中,我们实现了TextureView.SurfaceTextureListener,用于监听SurfaceTexture的生命周期事件。在onSurfaceTextureAvailable中,我们创建了一个绘制线程,在循环中不断地调用draw()方法来进行绘制工作。在onSurfaceTextureDestroyed中,我们停止了绘制线程,调用join()方法等待其结束。

五、GLSurfaceView的使用

GLSurfaceView是Android系统提供的一种可与OpenGL ES结合使用的视图,它可以对3D场景进行实时渲染。在需要实现动态图像和高级图形效果时,我们可以选择使用GLSurfaceView实现。

下面是一个简单的GLSurfaceView实现代码:

public class MyGLSurfaceView extends GLSurfaceView implements Renderer {

    private FloatBuffer vertexBuffer;
    private float[] vertices = {0f, 1f, -1f, -1f, 1f, -1f};

    public MyGLSurfaceView(Context context) {
        super(context);
        setEGLContextClientVersion(2);
        setRenderer(this);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // 初始化
        ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);
        gl.glClearColor(0f, 0f, 0f, 0f);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // TODO: Implement onSurfaceChanged()
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        // 渲染
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        gl.glColor4f(0f, 1f, 0f, 1f);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, vertices.length / 2);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }
}

在该实现中,我们重写了GLSurfaceView的三个生命周期方法,分别是onSurfaceCreated、onSurfaceChanged和onDrawFrame。在onSurfaceCreated中,我们初始化了一些OpenGL ES相关的属性和参数。在onDrawFrame中,我们对3D场景进行渲染操作,具体内容可以在OpenGL ES相关文档中找到。

原创文章,作者:KRTND,如若转载,请注明出处:https://www.506064.com/n/371617.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
KRTND的头像KRTND
上一篇 2025-04-23 18:08
下一篇 2025-04-23 18:08

相关推荐

  • Android ViewPager和ScrollView滑动冲突问题

    Android开发中,ViewPager和ScrollView是两个常用的控件。但是当它们同时使用时,可能会发生滑动冲突的问题。本文将从多个方面介绍解决Android ViewPa…

    编程 2025-04-28
  • Android如何点击其他区域收起软键盘

    在Android应用中,当输入框获取焦点弹出软键盘后,我们希望能够点击其他区域使软键盘消失,以提升用户体验。本篇文章将说明如何实现这一功能。 一、获取焦点并显示软键盘 在Andro…

    编程 2025-04-28
  • Android Studio HUD 实现指南

    本文将会以实例来详细阐述如何在 Android Studio 中使用 HUD 功能实现菊花等待指示器的效果。 一、引入依赖库 首先,我们需要在 build.gradle 文件中引入…

    编程 2025-04-27
  • Android和Vue3混合开发方案

    本文将介绍如何将Android和Vue3结合起来进行混合开发,以及其中的优势和注意事项。 一、环境搭建 在进行混合开发之前,需要搭建好相应的开发环境。首先需要安装 Android …

    编程 2025-04-27
  • Android Java Utils 可以如何提高你的开发效率

    Android Java Utils 是一款提供了一系列方便实用的工具类的 Java 库,可以帮助开发者更加高效地进行 Android 开发,提高开发效率。本文将从以下几个方面对 …

    编程 2025-04-27
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • git config user.name的详解

    一、为什么要使用git config user.name? git是一个非常流行的分布式版本控制系统,很多程序员都会用到它。在使用git commit提交代码时,需要记录commi…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25

发表回复

登录后才能评论