Android 中 View 與 SurfaceView 主動(dòng)與被動(dòng)更新的應(yīng)用場(chǎng)景

在 Android 開(kāi)發(fā)中,ViewSurfaceView 是兩種常用的視圖繪制組件。它們雖然都能用于繪制內(nèi)容,但其更新機(jī)制不同,分別適用于不同的場(chǎng)景。理解它們的區(qū)別,有助于在開(kāi)發(fā)中選擇合適的組件。


View 是 Android 中最常見(jiàn)的 UI 組件,它的繪制過(guò)程由系統(tǒng)的主線程(UI 線程)管理。通常情況下,View 只有在需要時(shí)才會(huì)刷新,比如當(dāng)我們調(diào)用 invalidate() 方法時(shí),系統(tǒng)會(huì)在下一次繪制周期內(nèi)更新視圖。這種機(jī)制被稱為主動(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)景包括用戶交互驅(qū)動(dòng)的 UI 更新,如點(diǎn)擊按鈕、滑動(dòng)手勢(shì)等。


2. SurfaceView:適用被動(dòng)更新,頻繁刷新

SurfaceView 則是另一種更適合高頻率繪制任務(wù)的組件。與 View 不同,SurfaceView 擁有自己的獨(dú)立繪制線程,通常在子線程中進(jìn)行復(fù)雜的繪制操作。這意味著 SurfaceView 能夠在主線程之外進(jìn)行繪制,并且支持更頻繁的內(nèi)容更新。被動(dòng)更新 指的是通過(guò)持續(xù)的刷新循環(huán)更新視圖內(nèi)容,適合用于高幀率動(dòng)畫、游戲渲染、視頻播放等場(chǎng)景。

示例

在游戲場(chǎng)景中,角色的移動(dòng)和場(chǎng)景的動(dòng)畫需要頻繁更新。這時(shí)可以使用 SurfaceView 并在獨(dú)立的線程中不斷刷新屏幕。

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);  // 清空畫布
                        // 其他繪制操作...
                    }
                } finally {
                    if (canvas != null) {
                        surfaceHolder.unlockCanvasAndPost(canvas);
                    }
                }
            }
        }
    }
}

總結(jié)

SurfaceView 適用于需要頻繁刷新和復(fù)雜渲染的場(chǎng)景。它通過(guò)獨(dú)立線程進(jì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ò)子線程不斷進(jìn)行繪制,適合游戲渲染、視頻播放等需要持續(xù)、頻繁更新的場(chǎng)景。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容