在Android平台中,SurfaceHolder是一种很重要的API接口,它可以被用来管理一个SurfaceView,并且可以对视频或者图像进行读写操作。SurfaceHolder的使用方法有许多技巧和细节需要注意,下面将详细介绍。
一、SurfaceView与SurfaceHolder
在介绍SurfaceHolder之前,先简单介绍一下它与SurfaceView的关系。SurfaceView是Android中的View控件,能够绘制视频、图像以及动画等多媒体资源,并支持用户交互。不同于其他的View控件,SurfaceView是另开一个新线程单独进行绘制,因此具备更高的绘图性能。而SurfaceHolder则是SurfaceView的一个内部接口,用来管理SurfaceView的状态,包括Surface的尺寸、格式与绘制逻辑等。
二、 SurfaceHolder的应用场景
1、视图组合
SurfaceView可以与其他View控件进行组合,以达到更复杂的UI展示效果。例如:在一个相对布局中添加一个SurfaceView,相对布局中还添加一个按钮,这时候SurfaceView和按钮在同一个视图组中,即可达到视图上的复合效果。
2、多线程绘制
我们知道,onDraw()方法是在UI线程执行绘制操作的。如果某个操作较费时,则会阻塞UI线程工作。而SurfaceHolder中有华丽的API接口,在SurfaceView基础上不再依赖UI线程,可以将其放到单独的工作线程中进行渲染操作,减轻UI线程的负担从而提高程序性能。
3、视频/图像渲染
SurfaceView的另一个很重要的用途是播放视频或绘制图像。这里SurfaceHolder会起到很关键的作用,它可以控制SurfaceView的状态并配合MediaPlayer或者一些绘图API对视频或图像进行渲染处理。
三、 SurfaceHolder的基本使用
1、getHolder()
我们知道在调用SurfaceHolder接口时,必须要先获取SurfaceHolder对象才能进行后续操作。在SurfaceView中,可以通过getHolder()方法获取到SurfaceHolder对象。
SurfaceHolder holder = surfaceView.getHolder();
2、setType()
SurfaceHolder接口中的函数setType()是用来设置SurfaceView的显示格式。默认显示格式为TYPE_NORMAL。常用的类型有TYPE_HARDWARE,TYPE_GPU,TYPE_NORMAL,TYPE_PUSH_BUFFERS等等。
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
3、addCallback()
addCallback()函数用于设置SurfaceHolderCallback回调接口。SurfaceHolderCallback回调接口中有三个回调函数,分别是surfaceChanged()、surfaceCreated()以及surfaceDestroyed()。这三个回调函数都是在UI线程中执行的。
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
//surface创建时的回调函数
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
//surface尺寸改变时的回调函数
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//surface销毁时的回调函数
}
});
4、lockCanvas()
lockCanvas()函数是锁定Surface画布,返回Canvas对象。在这个函数之后对画布所做的操作都能被提交到SurfaceView中。
Canvas canvas = holder.lockCanvas();
5、unlockCanvasAndPost()
执行完lockCanvas()操作之后,还需要执行unlockCanvasAndPost方法把画布释放掉,并提交到surface中,这样才能显示出我们画的图形。
holder.unlockCanvasAndPost(canvas);
四、 SurfaceHolder的常见问题及解决方案
1、surface系列函数的调用顺序
surfaceCreated() → surfaceChanged() → surfaceDestroyed()
在创建Surface时,先调用surfaceCreated(),在Surface View的大小或者格式发生变化时,调用surfaceChanged(),直至Surface被销毁,才会调用surfaceDestroyed()方法。
2、在回调函数中占用时间过长
在surfaceCreated()、surfaceChanged()和surfaceDestroyed()回调函数中,不要进行耗时的操作,否则会严重影响SurfaceView的性能,导致视觉卡顿的现象。
3、SurfaceView被覆盖时的处理
当SurfaceView被覆盖时,如果不希望SurfaceView被覆盖的部分展示出来,可以在SurfaceView的构造函数中设置setZOrderOnTop(true),将其置于顶层。
5、SurfaceView的透明度问题
SurfaceView透明度为0的话,SlidePanel或者其他View的透明度依然会跟着变,解决方案就是在SurfaceView的构造函数中调用setZOrderMediaOverlay(true),将其置于遮罩层。
六、总结
SurfaceHolder是在Android开发中不可或缺的API接口之一,它可以管理SurfaceView的状态,并支持视图组合、多线程绘制以及视频/图像渲染等操作。了解并掌握SurfaceHolder的使用方法在实际应用中非常重要,通过这篇文章的学习,相信大家对SurfaceHolder的应用技巧和实践已经有一个基本的理解了。