SurfaceView、GLSurfaceView、SurfaceTexture、TextureView、SurfaceHolder、Surface

本文详细介绍了Android中的SurfaceView、GLSurfaceView、SurfaceTexture和TextureView,讲解了它们在处理图像流和显示方面的区别和应用场景。SurfaceView拥有自己的Surface,适合高性能渲染;GLSurfaceView是SurfaceView的增强版,管理EGL环境,适用于3D渲染;SurfaceTexture不直接显示,而是作为GL外部纹理,用于图像流的二次处理;而TextureView是View hierarchy的一部分,可以进行动画和变换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SurfaceView、GLSurfaceViewe\SurfaceTexture、TextureView、SurfaceHolder、Surface


一、简介

SurfaceTexture: SurfaceTexture是从Android3.0(API 11)加入的一个新类。这个类跟SurfaceView很像,可以从video decode里面获取图像流(image stream)。但是,和SurfaceView不同的是,SurfaceTexture在接收图像流之后,不需要显示出来。SurfaceTexture不需要显示到屏幕上,因此我们可以用SurfaceTexture接收来自decode出来的图像流,然后从SurfaceTexture中取得图像帧的拷贝进行处理,处理完毕后再送给另一个SurfaceView用于显示即可

Surface: 处理被屏幕排序的原生的buffer,Android中的Surface就是一个用来画图形(graphics)或图像(image)的地方,对于View及其子类,都是画在Surface上,各Surface对象通过Surfaceflinger合成到frameBuffer,每个Surface都是双缓冲(实际上就是两个线程,一个渲染线程,一个UI更新线程),它有一个backBuffer和一个frontBuffer,Surface中创建了Canvas对象,用来管理Surface绘图操作,Canvas对应Bitmap,存储Surface中的内容(Surface可以理解成是用来管理Canvas画布的,而Canvas用来存储图像数据的)。

SurfaceView: 这个可能经常被说起,在Camera,MediaRecorder,MediaPlayer中用来显示图像的。SurfaceView是View的子类,且实现了Parcelable接口,其中内嵌了一个专门用于绘制的SurfaceSurfaceView可以控制这个Surface的格式和尺寸,以及Surface的绘制位置。可以理解为**Surface就是管理数据的地方,SurfaceView就是展示数据的地方**。

SurfaceHolder:顾名思义,一个管理Surface的容器。SurfaceHolder是一个接口,可理解为一个Surface的监听器
通过回调方法addCallback(SurfaceHolder.Callback callback )监听Surface的创建、改变、销毁等。通过获取Surface中的Canvas对象,并锁定所得到的Canvas对象,当修改Surface中的数据完成后,释放同步锁,并提交改变Surface的状态及图像,将新的图像数据进行展示。

而最后综合:SurfaceView中调用getHolder方法,可以获得当前SurfaceView中的Surface对应的SurfaceHolder,SurfaceHolder开始对Surface进行管理操作。这里其实按MVC模式理解的话,可以更好理解。M:Surface(图像数据),V:SurfaceView(图像展示),C:SurfaceHolder(图像数据管理)


1、 SurfaceView

从Android 1.0(API level 1)时就有 。它继承自类View,因此它本质上是一个View。但与普通View不同的是,它有自己的Surface。我们知道,一般的Activity包含的多个View会组成View hierachy的树形结构,只有最顶层的DecorView,也就是根结点视图,才是对WMS可见的,这个DecorView在WMS中有一个对应的WindowState。相应地,在SF中对应的Layer。SurfaceView自带一个Surface,这个Surface在WMS中有自己对应的WindowState,在SF中也会有自己的Layer。如下图所示:

在这里插入图片描述


也就是说, 虽然在Client端(App)它仍在View hierachy中,但在Server端(WMS和SF)中,它与宿主窗口是分离的(可以理解成其他的View在一个窗口中,SurfaceView中的Surface单独占用一个窗口)。这样的好处是**对这个Surface的渲染可以放到单独线程去做,渲染时可以有自己的GL context。这对于一些游戏、视频等性能相关的应用非常有益,因为它不会影响主线程对事件的响应。但它也有缺点,因为这个Surface不在View hierachy中,它的显示也不受View的属性控制,所以不能进行平移,缩放等变换,也不能放在其它ViewGroup中,一些View中的特性也无法使用**。


通过源码发现,SurfaceView里面其实就是创建了一个Surface,Surface主要的实现就是管理里面的Canvas的打开、关闭等,以及监听这个Surface的创建、改变、销毁、锁定里面的Canvas以及解锁等操作的SurfaceHolder,以及一些使里面的Surface占用独立窗口的一些操作。

final Surface mSurface = new Surface(); // Current surface in use

/**
296     * Return the SurfaceHolder providing access and control over this
297     * SurfaceView's underlying surface.
298     *
299     * @return SurfaceHolder The holder of the surface.
300     */
301    public SurfaceHolder getHolder() {
   
302        return mSurfaceHolder;
303    }
304
 @UnsupportedAppUsage
1616    private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
   
1617        private static final String LOG_TAG = "SurfaceHolder";
1618
1624        @Override
1625        public void addCallback(Callback callback) {
   
1626            synchronized (mCallbacks) {
   
1627                // This is a linear search, but in practice we'll
1628                // have only a couple callbacks, so it doesn't matter.
1629                if (!mCallbacks.contains(callback)) {
   
1630                    mCallbacks.add(callback);
1631                }
1632            }
1633        }
1634
1635        @Override
1636        public void removeCallback(Callback callback) {
   
1637            synchronized (mCallbacks) {
   
1638                mCallbacks.remove(callback);
1639            }
1640        }
1641
1683
1684        /**
1685         * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
1686         *
1687         * After drawing into the provided {@link Canvas}, the caller must
1688         * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
1689         *
1690         * The caller must redraw the entire surface.
1691         * @return A canvas for drawing into the surface.
1692         */
1693        @Override
1694        public Canvas lockCanvas() {
   
1695            return internalLockCanvas(null, false);
1696        }
1697
1698        /**
1699         * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
1700         *
1701         * After drawing into the provided {@link Canvas}, the caller must
1702         * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
1703         *
1704         * @param inOutDirty A rectangle that represents the dirty region that the caller wants
1705         * to redraw.  This function may choose to expand the dirty rectangle if for example
1706         * the surface has been resized or if the previous contents of the surface were
1707         * not available.  The caller must redraw the entire dirty region as represented
1708         * by the contents of the inOutDirty rectangle upon return from this function.
1709         * The caller may also pass <code>null</code> instead, in the case where the
1710         * entire surface should be redrawn.
1711         * @return A canvas for drawing into the surface.
1712         */
1713        @Override
1714        public Canvas lockCanvas(Rect inOutDirty) {
   
1715            return internalLockCanvas(inOutDirty, false);
1716        }
1717
1718        @Override
1719        public Canvas lockHardwareCanvas() {
   
1720            return internalLockCanvas(null, true);
1721        }

 private void setWindowStopped(boolean stopped) {
   
310        mWindowStopped = stopped;
311        updateRequestedVisibility();
312        updateSurface();
313    }
314
315    @Override
316    protected void onAttachedToWindow() {
   
317        super.onAttachedToWindow();
318
319        getViewRootImpl().addSurfaceChangedCallback(this);
320        mWindowStopped = false;
321
322        mViewVisibility = getVisibility() == VISIBLE;
323        updateRequestedVisibility();
324
325        mAttachedToWindow = true;
326        mParent.requestTransparentRegion(SurfaceView.this);
327        if (!mGlobalListenersAdded) {
   
328            ViewTreeObserver observer = getViewTreeObserver();
329            observer.addOnScrollChangedListener(mScrollChangedListener);
330            observer.addOnPreDrawListener(mDrawListener);
331            mGlobalListenersAdded = true;
332        }
333    }
334

SurfaceView总结:里面会创建一个Surface,Surface主要管理Canvas画布对象的打开、关闭等操作,同时还有一个专门监听Surface创建、销毁、改变、里面的Canvas锁定等操作的SurfaceHolder,以及让Surface能够独占一个窗口的一系列操作。


2、GLSurfaceView

从Android 1.5(API level 3)开始加入,作为SurfaceView的补充。它可以看作是SurfaceView的一种典型使用模式。在SurfaceView的基础上,它加入了EGL的管理,并自带了渲染线程。另外它定义了用户需要实现的Render接口,提供了用Strategy pattern更改具体Render行为的灵活性。作为GLSurfaceView的Client,只需要将实现了渲染 函数的Renderer的实现类设置给GLSurfaceView即可。如:

public class TriangleActivity extends Activity {
     
    protected void onCreate(Bundle savedInstanceState) {
     
        mGLView = new GLSurfaceView(this);  
        mGLView.setRenderer(new RendererImpl(this));  

相关类图如下。其中SurfaceView中的SurfaceHolder主要是提供了一坨操作Surface的接口**。GLSurfaceView中的EglHelper和GLThread分别实现了上面提到的管理EGL环境和渲染线程的工作。GLSurfaceView的使用者需要实现Renderer接口**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值