时间:2022-09-08 09:01:08 | 栏目:Android代码 | 点击:次
SurfaceView
从源码上看继承自View
,但在内部实现上SurfaceView
和其他View
有很多区别。 SurfaceView
主要作用是提供一个直接绘图表面嵌入到视图结构中,实际上真正做绘制能力的是Surface
。因此SurfaceView
和宿主窗口是分离的。正常情况下窗口的View
共享同一个Window
,而Window
也对应一个Surface
,所有View
也就共享同一个Surface
。所以SurfaceView
具备独立的Surface
,相当于和宿主窗口绘制是分离互不干扰。
不同点 | SurfaceView | View |
---|---|---|
绘制 | 结构在View当中,但绘制表面是独立的。内部拥有自己的Canvas进行绘制操作 | 和宿主窗口共享同一个绘图表面 |
刷新 | 窗口刷新不需要重绘宿主窗口 | 任何一个子元素或是局部刷新都会使得整个视图结构发生重绘 |
线程 | 线程独立,不影响主线程 使用界面频繁刷新 | 在UI主线程使用 |
操作 | 低版本不支持平移、缩放、旋转等动画 不具备View属性控制 | 均可正常操作 |
刷新 | 可控制刷新频率、双缓存机制 | 只在主线程刷新更新 |
SurfaceView
将视频流解析成一帧帧图像数据显示。例如一帧图像显示后,等待下一帧图像可能存在还未及时解析的情况,这种情况下就会导致画面不流畅。利用双缓冲可以避免这种情况,可以理解双缓冲是两个线程轮流解析视频流图像数据两者交替进行解析和渲染操作从而保证视频流能够流畅播放。
SurfaceView
双缓冲机制事实上是比较消耗系统内存。因此当SurfaceView
在不可见状态下就会去销毁SurfaceHolder
来减轻内存开销。因此就有了SurfaceHolder
的addCallback
方法来监听SurfaceHolder
状态。
自定义继承SurfaceView
可以自定义绘制内容。当创建SurfaceHolder
成功后再surfaceCreated
回调中调用lockCanvas
获取到SurfaceHolder
的画布并锁定,然后绘制内容。绘制结束后调用unlockCanvasAndPost
释放并提交画布改动信息,让新数据在画布上进行展示。
public class SurfaceViewTest extends SurfaceView implements SurfaceHolder.Callback{ private SurfaceHolder mSurfaceHolder; private Canvas mCanvas; private Paint paint; public SurfaceViewTest(Context context) { this(context,null,0); } public SurfaceViewTest(Context context, AttributeSet attrs) { this(context, attrs,0); } public SurfaceViewTest(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mSurfaceHolder = getHolder(); // 初始化 mSurfaceHolder.addCallback(this); setFocusable(true); setFocusableInTouchMode(true); this.setKeepScreenOn(true); paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.RED); paint.setStrokeWidth(5); paint.setStyle(Paint.Style.STROKE); } @Override public void surfaceCreated(SurfaceHolder holder) { // 创建成功后就能通过线程绘制自定义内容 new Thread(new Runnable() { @Override public void run() { draw(); } }).start(); } private void draw() { try { mCanvas = mSurfaceHolder.lockCanvas(); mCanvas.drawCircle(500,500,300,paint); mCanvas.drawCircle(100,100,20,paint); } catch (Exception e) { e.printStackTrace(); } finally { if (mCanvas != null) mSurfaceHolder.unlockCanvasAndPost(mCanvas); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} @Override public void surfaceDestroyed(SurfaceHolder holder) {} }