安卓 SurfaceView 和 View 的區別和使用方法

Android 系統提供了 View 進行繪圖處理,View 可以滿足大部分的繪圖需求,但在某些時候,View 通過刷新來重繪視圖,Android 系統通過發出 vsync 信號來進行屏幕重繪,刷新的間隔時間為 16ms,如果在這個時間間隔內完成了你所需要執行的所有操作,那么在視覺上,就不會產生卡頓的感覺,而如果執行的操作邏輯太多,特別再需要頻繁刷新的界面上,例如游戲界面,那么就會不斷阻塞主線程,從而導致界面卡頓,為了避免這個問題,Android 系統提供了 surfaceView 組件來解決這個問題。surfaceView 和 View 的區別主要有下面幾點:

  • View 主要適用于主動更新的情況,而 surfaceView 主要適用于被動更新,例如頻繁的刷新。
  • View 在主線程中對畫面進行刷新,而 surfaceView 通常會通過一個子線程來進行頁面的刷新
  • View 在繪圖時沒有使用雙緩沖機制,而 surfaceView 在底層實現機制上就已經實現了雙緩沖機制。
    總結就是,如果你的自定義 View 需要頻繁刷新,或者刷新時數據處理量很大,考慮用 SurfaceView 來替代 View。

surfaceView 的使用

  • 創建 SurfaceView,一般我們實現 SurfaceHolder.Callback, Runnable接口
    //surfaceView 的創建
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsDraw = true;
    }
    //surfaceView 的改變
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }
    //surfaceView 的銷毀
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDraw = false;
    }
 //runnable 的run 方法中,我們可以執行繪制的操作
    @Override
    public void run() {
        while (mIsDraw) {
            draw();
        }
    }
  • 初始化 surfaceView
mHolder = getHolder();
mHolder.addCallback(this);
//通過 lockCanvas 方法可以獲得當前的 canvas 繪圖對象,接下來,就可以與在 View 中進行的繪制操作一樣了
mCanvas = mHolder.lockCanvas();
//通過 unlockCanvasAndPost 方法可以對當前畫布內容進行提交。
mHolder.unlockCanvasAndPost(mCanvas);

下面是一個 surfaceView 使用的模板,基本上可以在這個基礎上來修改滿足大部分的繪圖需求。

public class SurfaceViewDemo extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    private SurfaceHolder mHolder;
    private boolean mIsDraw;
    private Canvas mCanvas;

    public SurfaceViewDemo(Context context) {
        super(context);
        initView();
    }

    public SurfaceViewDemo(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initView();
    }


    private void initView() {
        mHolder = getHolder();
        mHolder.addCallback(this);
        setFocusable(true);
        setFocusableInTouchMode(true);
        setKeepScreenOn(true);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsDraw = true;
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDraw = false;
    }

    //runnable 的run 方法中,我們可以執行繪制的操作
    @Override
    public void run() {
        while (mIsDraw) {
            draw();
        }
    }

    private void draw() {
        mCanvas = mHolder.lockCanvas();
        //draw something
        
        mHolder.unlockCanvasAndPost(mCanvas);
    }
}

下面是一些 surfaceView 的實例源碼的地址:https://github.com/MoveToNext/SurfaceViewDemo

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容