Android音视频开发系列-SurfaceView绘制过程解析

2,331 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

前言

Android系统中在一个窗口下所有View是共用同一个SurfaceSurface保存在ViewRootImpl中。然而SurfaceView比较特殊,它和其他View不同点就是独立使用一个Surface。因此SurfaceView渲染效率上更搞笑,因为更新时不需要通知ViewRootImpl去执行刷新工作。

源码分析

SurfaceView源码分析主要关注SurfaceSurfaceHolderSurfaceView三个类。

Surface

Surface实现了Parcelable接口序列化对象以便于进程数据传递,该对象主要用于存储处理屏幕显示缓冲区的数据。Surface相当于是图像缓冲区的句柄,内部HwuiContext对应硬件层图像画布数据。

public class Surface implements Parcelable {
    private static final String TAG = "Surface";

    private static native long nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
            throws OutOfResourcesException;

    private static native long nativeCreateFromSurfaceControl(long surfaceControlNativeObject);
    private static native long nativeGetFromSurfaceControl(long surfaceObject,
            long surfaceControlNativeObject);

    private static native long nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty)
            throws OutOfResourcesException;
    private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas);

 ......
}

Surface中也包含Canvas对象(CompatibleCanvas)作为内部类。主要作用是兼容Android各种分辨率屏幕处理不同屏幕分辨率图像数据。

private final class CompatibleCanvas extends Canvas {
    @Override
    public void setMatrix(Matrix matrix) {
        if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
            // don't scale the matrix if it's not compatibility mode, or
            // the matrix was obtained from getMatrix.
            super.setMatrix(matrix);
        } else {
            Matrix m = new Matrix(mCompatibleMatrix);
            m.preConcat(matrix);
            super.setMatrix(m);
        }
    }

    @SuppressWarnings("deprecation")
    @Override
    public void getMatrix(Matrix m) {
        super.getMatrix(m);
        if (mOrigMatrix == null) {
            mOrigMatrix = new Matrix();
        }
        mOrigMatrix.set(m);
    }
}

其次在Surface中还有两个比较重要方法lockCanvasunlockCanvasAndPost。实际上就是SurfaceHolder接口方法对接调用的方法(SurfaceHolder接口由BaseSurfaceHolder抽象类来实现)其最终还是有JNI层具体实现。

SurfaceHolder

SurfaceHolder接口是作为Controller角色存在。主要用来控制Surface大小、格式、监听Surface变化。其关键接口是Callback,实现该接口可以控制绘制动画线程,也就是开发SurfaceView熟悉的三个回调方法。在获取实例化的SurfaceHolder同时能够获取到底层实际与底层交互的Surface对象从而能够和底层图像进行交互操作。

  • surfaceCreated(SurfaceHolder holder)
  • surfaceChanged(SurfaceHolder holder,int format,int width,int height)
  • surfaceDestroyed(SurfaceHolder holder)

SurfaceView

SurfaceView作为特殊的View继承MockView。实现绘制主要在SurfaceSurfaceHolder上而非SurfaceView

  • 主要作用是在视图屏幕上嵌入独立的图像绘制视图。
  • SurfaceView实例化后Surface并不会马上创建,因为是异步创建。因此需要使用CallBack接口来获取到Surface
public class SurfaceView extends MockView {

public SurfaceHolder getHolder() {
    return mSurfaceHolder;
}

private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
......
}
......
}

image.png

源码参考