close

今天我們就來講講 SurfaceView 吧!!


由於我們的標題打的是入門分析
在這裡我會寫個簡化版的 SurfaceView 分析
如果想知道整個底層的運作狀況的話
可以點擊下方的連結喔!!

 

點我看 SurfaceView 的完整底層運作(文長)

 

首先,我們介紹一下SurfaceView 的特色
它擁有獨立的繪圖表面
所以不會和父級ui共享同一個繪圖表面
由於它擁有獨立的繪圖表面
因此SurfaceView的UI就可以在一個獨立的線程中進行繪製

 

而且獨立線程不會占用主線程資源
所以SurfaceView一方面可以實現複雜而高效的UI
另一方面又不會導致用戶輸入得不到及時響應

 

SurfaceView里內嵌了一個專門用於繪製的Surface
這個可以比喻為一個在View里的Canvas
你可以控制這個Surface的格式和尺寸
Surfaceview類則控制這個Surface在螢幕上的正確位置


=============================

Android遊戲開發中常用的三種視圖是:

View:必須在UI主線程內更新畫面,速度較慢,提供圖形繪製函數、觸屏事件、按鍵事件函數等

SurfaceView:適合2D遊戲的開發;是view的子類,類似使用雙緩機制,在新的線程中更新畫面所以刷新介面速度比view快。

GLSurfaceView:基於SurfaceView視圖再次進行拓展的視圖類,專用於3D遊戲開發的視圖;是SurfaceView的子類,openGL專用。

=============================

 

而SurfaceView 在遊戲開發的優勢是在於
SurfaceView是用新的線程更新畫面所以不會阻塞UI主線程
一般來說如果更新畫面的時間過長
那麼UI主線程會被正在繪圖的函數阻塞
那麼將無法響應按鍵,觸屏等消息。


比如一個人在一直跑動
這就需要一個單獨的thread不停的重繪人的狀態
來避免阻塞main UI thread

 

剛剛提到SurfaceView里內嵌了一個專門用於繪製的Surface
那麼這兩個的合作關係是什麼呢?
Surface是管理顯示內容的數據(implementsParcelable),包括存儲與數據的交換
而SurfaceView就是把這些數據顯示出來到螢幕上面。



那麼要如何使用SurfaceView 呢?
這裡要說明SurfaceHolder & SurfaceHolder.Callback

 

在Android 中,如果要進行UI的繪製,會有下面三個步驟

 

1、在繪圖表面上建立 Canvas

 

2、利用 Canvas 來繪製我們需要的 UI

 

3、繪製完成後提交給SurfaceFilnger 服務,它會讓我們繪製出來的 UI 合成到螢幕上面

 

SurfaceView 提供了 getHolder() 這個 method 來獲取 SurfaceHolder
取得的 SurfaceHolder 就可以做到上面的第 1 點 & 第 3 點

Canvas canvas = null;
SurfaceHolder holder = surfaceView.getHolder();
canvas = holder.lockCanvas();//第 1 點 獲取 Canvas 

// Draw something on canvas
......

holder.unlockCanvasAndPost(canvas);//第 3 點 結束鎖定畫布並提交改變

這裡要注意一點
SurfaceView 有一個變數為 mRequestedType 指得是繪圖表面的類型
它的值可能是SURFACE_TYPE_NORMAL,或是SURFACE_TYPE_PUSH_BUFFERS

 

只有當 SurfaceView 的 type值不是 SURFACE_TYPE_PUSH_BUFFERS 的時候
我們才可以自由的繪製UI
因為當類型為 PUSH_BUFFERS 時
畫面是由數據源源不絕的輸入進 SurfaceView 的分配內存中
然後不斷的更新畫面,例如:視頻播放服務、攝影機…等。

 

同時,SurfaceFlinger服務會用一種特別的 LayerBuffer 來進行繪圖的渲染
當使用 LayerBuffer 來運作時
可以使用進行硬件加速,例如: copybit 或是 overlay
讓我們可以獲得更流蜴的攝影機預覽or視頻播放

 

接下來介紹一些SurfaceHolder在控制Surface流程時所用到的方法

//加入 & 移除 一個 Callback
void addCallback(SurfaceHolder.Callback var1);
void removeCallback(SurfaceHolder.Callback var1);

//鎖定畫布,並返回一個 Canvas
Canvas lockCanvas();
//lockCanvas(Rect)
可以鎖定畫布中的某一個區域,返回的畫布對象Canvas
(當更新的內容只有一個區域時,同時要追求高效
可以只更新一部分的區域,而不必更新全部畫布區域)
Canvas lockCanvas(Rect var1);

//解鎖畫布,並提交改變
void unlockCanvasAndPost(Canvas var1);

 

 

再來是第二部分 SurfaceHolder.Callback 的介紹
SurfaceHolder.Callback 是一個監聽 SurfaceView 改變的一個接口
只要是建立、改變、銷毀時,都有對應的 method 去做監聽

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {}

@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {}


以上就是 SurfaceView 的介紹與使用方式囉!
不過我們既然要在 SurfaceView 上繪圖
那就不得不提到
Paint & Canvas 這兩個類了
下方的連結有他們的相關介紹喔
我們快去看看吧

 

我是 Paint 介紹(點我)

我是 Canvas 介紹(點我)



參考資料:
https://developer.android.com/reference/android/view/SurfaceView.html
http://blog.csdn.net/luoshengyang/article/details/8661317
https://read01.com/5x6xEz.html


arrow
arrow
    全站熱搜

    顏澤偉 發表在 痞客邦 留言(0) 人氣()