初识SurfaceView
刚开始做android app开发的时候,我觉得在app上展示播放一段视频,是一件很高大上的事情,后来研究了一下,原来,这都要归功于SurfaceView这个东东。
Surface + View
怎么理解SurfaceView呢?顾名思义就是Surface+View了,因此,这个东西有两重身份:首先,是一个View;其次还是一个带有Surface的View。首先聊聊View,View我们可以理解为视图了,android上的imageview,textview之类的,都可以理解为视图,这些视图可以直接在layout上规划。所以,SurfaceView,类似的,也可以直接在xml上规划。再来聊聊Surface,Surface可以理解为一块画布,应用可以在Surface上绘制自己的图像。对于视频而言,其本质,也是图像,只不过是在不断变化的图像,确切的说,是每秒变化30帧的图像(30fps)。
总结起来,SurfaceView本身是一个视图,可以在layout中布局,在这个视图中有一个画布是Surface,我们可以将图片绘制在这个Surface上。
类图
下面用类图介绍一下SurfaceView的大致框架
SurfaceView.png
这个类图以camera预览为场景,介绍SurfaceView,从类图中可以看出,SurfaceView继承自(is-a)View,另外,SurfaceView中有一个SurfaceHolder,可以通过getHolder得到这个holder,这个holder有一个方法addCallback,可以向这个类中注册一个Callback,并且SurfaceHolder中有一个(has-a)Surface。Camera中通过setPreviewDisplay像Camera注册一个SurfaceHolder,这样底层的Camera就可以将图像渲染在SurfaceHolder的Surface中,最后SurfaceFlinger会将所有应用的Surface进行混合,我们在手机看到的,就是最终混合的效果。
课题讨论
为什么要有SurfaceHolder.Callback ?
既然SurfaceView具有双重身份,我们直接在Surface上绘制不就可以了?为何需要注册一个SurfaceHolder.Callback回调呢?我觉得初识SurfaceView的同学,可能也会被这个回调吓到,想想Android中有那么多视图,TextView,ImageView等等,都不需要注册类似的回调函数,为何SurfaceView如此特殊?我的理解是,SurfaceView固然存在双重身份,但我们在xml中注册后,仅仅可以保证这个View已经初始化好了,但是Surface可未必已经初始化好了,如果此时就在View中直接注册的话,有可能系统就会崩溃吧。那我们如何知道这个Surface确实已经创建成功了?这就有两种方式:同步的方式和异步的方式。同步的方式就是一直等待Surface的初始化,Surface初始化好后再往下进行,在这个过程中,系统一直处于阻塞状态;另一种方式就是异步方式,也就是注册一个回调函数,当Surface创建好后,通过这个监听的函数,告知上层应用。回忆一下MediaPlayer就有类似的两种方式。在这里,SurfaceView采用的是第二种方式,我觉得主要原因可能是由于SurfaceView本身是在主线程中创建的,我们总不能让主线程阻塞吧!既然是异步方式,当然就需要注册监听函数了,这也就是SurfaceHolder.Callback的作用了。因此,我们需要向底层注册一个回调函数,在SurfaceView创建时或者改变时或者销毁时,告诉我们一下,我们好做相应的处理。
SurfaceHolder的作用
既然SurfaceView就是Surface+View,那为何要设计SurfaceHolder呢?我想可以这样理解,Surface只不过是SurfaceHolder的其中一个侧面,确切的说,可以理解为画布,而很多其他的侧面,比如和外部打交道等,都由SurfaceHolder来管理就可以了,这样Surface可以专心致志的干他需要干的事情。实际上在Android中有很多类似的模块,都采用这种类似的模式,比如XXXManager,XXXMaster等等,都采用了类似的处理方式。因此,对于外部而言,也不必知道Surface的存在,他们只要拿到SurfaceHolder就足够了,比如在Camera预览时,在setPreviewDisplay时,将SurfaceHolder传入就可以了。特别的,在SurfaceHolder.Callback的三个回调函数中,都会以参数的形式将SurfaceHolder传回,这样我们可以更方便的使用这个holder。