在 Android 開(kāi)發(fā)中,View
和 SurfaceView
是兩種常用的視圖繪制組件睛琳。它們雖然都能用于繪制內(nèi)容,但其更新機(jī)制不同踏烙,分別適用于不同的場(chǎng)景师骗。理解它們的區(qū)別,有助于在開(kāi)發(fā)中選擇合適的組件讨惩。
View
是 Android 中最常見(jiàn)的 UI 組件辟癌,它的繪制過(guò)程由系統(tǒng)的主線(xiàn)程(UI 線(xiàn)程)管理。通常情況下荐捻,View
只有在需要時(shí)才會(huì)刷新黍少,比如當(dāng)我們調(diào)用 invalidate()
方法時(shí),系統(tǒng)會(huì)在下一次繪制周期內(nèi)更新視圖处面。這種機(jī)制被稱(chēng)為主動(dòng)更新厂置,因?yàn)殚_(kāi)發(fā)者需要顯式請(qǐng)求視圖更新。
示例:
假設(shè)有一個(gè)按鈕魂角,點(diǎn)擊按鈕后改變其背景顏色昵济。此時(shí)可以在 onClick()
方法中調(diào)用 invalidate()
來(lái)觸發(fā)更新。系統(tǒng)將會(huì)在下一個(gè)繪制周期重新繪制這個(gè)按鈕野揪。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
button.setBackgroundColor(Color.RED);
button.invalidate(); // 主動(dòng)請(qǐng)求重新繪制
}
});
總結(jié):
View
適用于不需要頻繁刷新的場(chǎng)景访忿,通過(guò)事件觸發(fā)或手動(dòng)調(diào)用 invalidate()
,系統(tǒng)會(huì)在下一次繪制周期中進(jìn)行更新斯稳。典型應(yīng)用場(chǎng)景包括用戶(hù)交互驅(qū)動(dòng)的 UI 更新海铆,如點(diǎn)擊按鈕、滑動(dòng)手勢(shì)等挣惰。
2. SurfaceView:適用被動(dòng)更新游添,頻繁刷新
SurfaceView
則是另一種更適合高頻率繪制任務(wù)的組件。與 View
不同通熄,SurfaceView
擁有自己的獨(dú)立繪制線(xiàn)程唆涝,通常在子線(xiàn)程中進(jìn)行復(fù)雜的繪制操作。這意味著 SurfaceView
能夠在主線(xiàn)程之外進(jìn)行繪制唇辨,并且支持更頻繁的內(nèi)容更新廊酣。被動(dòng)更新 指的是通過(guò)持續(xù)的刷新循環(huán)更新視圖內(nèi)容,適合用于高幀率動(dòng)畫(huà)赏枚、游戲渲染亡驰、視頻播放等場(chǎng)景晓猛。
示例:
在游戲場(chǎng)景中,角色的移動(dòng)和場(chǎng)景的動(dòng)畫(huà)需要頻繁更新凡辱。這時(shí)可以使用 SurfaceView
并在獨(dú)立的線(xiàn)程中不斷刷新屏幕戒职。
class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private GameThread gameThread;
public GameSurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
gameThread = new GameThread(holder);
gameThread.setRunning(true);
gameThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameThread.setRunning(false);
while (retry) {
try {
gameThread.join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class GameThread extends Thread {
private SurfaceHolder surfaceHolder;
private boolean running;
public GameThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
while (running) {
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
// 執(zhí)行頻繁的繪制操作
canvas.drawColor(Color.BLACK); // 清空畫(huà)布
// 其他繪制操作...
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
}
總結(jié):
SurfaceView
適用于需要頻繁刷新和復(fù)雜渲染的場(chǎng)景。它通過(guò)獨(dú)立線(xiàn)程進(jìn)行渲染透乾,避免了主線(xiàn)程的阻塞洪燥,特別適合游戲、視頻播放或需要高幀率更新的場(chǎng)景乳乌。
3. 主動(dòng)更新 vs 被動(dòng)更新 總結(jié)
-
View 的主動(dòng)更新:適合不頻繁更新的操作捧韵,如按鈕點(diǎn)擊、UI 交互汉操。這些更新通過(guò)
invalidate()
請(qǐng)求再来,由系統(tǒng)在下一個(gè)繪制周期進(jìn)行處理。適合大部分 UI 控件的場(chǎng)景磷瘤。 - SurfaceView 的被動(dòng)更新:適用于高頻更新的場(chǎng)景芒篷,通過(guò)子線(xiàn)程不斷進(jìn)行繪制,適合游戲渲染采缚、視頻播放等需要持續(xù)梭伐、頻繁更新的場(chǎng)景。