Android SurfaceView简介与使用
更新日期:2022-6-9
SurfaceView 简介
SurfaceView在Android系统中,是一种特殊的视图。它拥有独立的绘图表面,即它不与宿主窗口共享同一个绘图表面。
由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制,又由于不会占用主线程资源,
运用SurfaceView可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应。
比较适合应用在视频播放,图片浏览,对画面要求高的游戏上面。
SurfaceView相当于是在屏幕里面,而屏幕给它开了一个洞。给它设置背景色就能把它盖住。
使用SurfaceView的原因之一,是能够在子线程中更新图像。减轻UI线程的压力。
所有SurfaceView和SurfaceHolder.Callback的方法都应该在UI线程里调用,一般来说就是应用程序主线程。
渲染线程所要访问的各种变量应该作同步处理。要确保绘图线程仅在surface可用期间进行绘图。
SurfaceView主要由SurfaceHolder来控制,holder相当于一个控制器。
核心要点
View:必须在UI的主线程中更新画面,用于被动更新画面。
SurfaceView:UI线程和子线程中都可以。在一个新启动的线程中重新绘制画面,主动更新画面。
java.lang.Object
↳ android.view.View
↳ android.view.SurfaceView
SurfaceView 使用方法
创建一个类继承SurfaceView并实现SurfaceHolder.Callback
接口。
public class MySView extends SurfaceView implements SurfaceHolder.Callback {
.........
}
获取SurfaceHolder
在构造函数中获取SurfaceHolder。并添加回调。
| public MySView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
holder = getHolder();
holder.addCallback(this);
// ......
}
|
复写方法
| @Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated");
drawThread = new DrawThread(holder);// 创建一个绘图线程
drawThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d(TAG, "surfaceChanged");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
drawThread.closeThread();// 销毁线程
Log.d(TAG, "surfaceDestroyed");
}
|
当Activity不可见时,SurfaceView会调用surfaceDestroyed
方法。此时就要销毁绘图线程。
绘图子线程
SurfaceView中绘图操作是在子线程中进行的。正常来说子线程不能操作UI。但是我们可以使用
SurfaceHolder提供的方法锁定画布,绘图完成后释放并更新画布。
下面的线程提供了停止、恢复和结束等功能。
| class DrawThread extends Thread {
private SurfaceHolder mmHolder;
private boolean mmRunning;
private boolean mmIsPause;
public DrawThread(SurfaceHolder holder) {
this.mmHolder = holder;
mmRunning = true;
}
@Override
public void run() {
while (mmRunning && !isInterrupted()) {
if (!mmIsPause) {
Canvas canvas = null;
try {
synchronized (mmHolder) {
canvas = holder.lockCanvas(); // 锁定画布,获得返回的画布对象Canvas
canvas.drawColor(bgSurfaceViewColor);// 设置画布背景颜色
// 绘图操作......
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null) {
mmHolder.unlockCanvasAndPost(canvas);// 释放画布,并提交改变。
}
pauseThread();
}
} else {
onThreadWait();
}
}
}
public synchronized void pauseThread() {
mmIsPause = true;
}
/**
* 线程等待,不提供给外部调用
*/
private void onThreadWait() {
try {
synchronized (this) {
this.wait();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void resumeThread() {
mmIsPause = false;
this.notify();
}
public synchronized void closeThread() {
try {
mmRunning = false;
notify();
interrupt();
} catch (Exception e) {
e.printStackTrace();
}
}
}
|
layout中使用
切记不可在layout中设置background,颜色会直接把SurfaceView挡住。
| <com.rustfisher.fisherandroidchart.MySView
android:id="@+id/mySurfaceView"
android:layout_width="match_parent"
android:layout_height="230dp" />
|
参考
本站说明
一起在知识的海洋里呛水吧。广告内容与本站无关。如果喜欢本站内容,欢迎投喂作者,谢谢支持服务器。如有疑问和建议,欢迎在下方评论~
📖AndroidTutorial
📚AndroidTutorial
🙋反馈问题
🔥最近更新
🍪投喂作者
Ads