Android中Surface和SurfaceView的一些理解和總結

什麼是Surface?
簡單地說Surface對應瞭一塊屏幕緩沖區,每個window對應一個Surface,任何View都是畫在Surface上的,傳統的view共享一塊屏幕緩沖區,所有的繪制必須在UI線程中進行
什麼是SurfaceView?
說SurfaceView是一個View也許不夠嚴謹,然而從定義中 public class SurfaceView extends View {…}顯示SurfaceView確實是派生自View,但是SurfaceView卻有著自己的Surface,繼續看SurfaceView的源碼:
[java] view plaincopy
if (mWindow == null) { 
      mWindow = new MyWindow(this); 
      mLayout.type = mWindowType; 
      mLayout.gravity = Gravity.LEFT|Gravity.TOP; 
      mSession.addWithoutInputChannel(mWindow, mWindow.mSeq, mLayout, 
      mVisible ? VISIBLE : GONE, mContentInsets); 

很明顯,每個SurfaceView創建的時候都會創建一個MyWindow,new MyWindow(this)中的this正是SurfaceView自身,因此將SurfaceView和window綁定在一起,而前面提到過每個window對應一個Surface,所以SurfaceView也就內嵌瞭一個自己的Surface,可以認為SurfaceView是來控制Surface的位置和尺寸。大傢都知道,傳統View及其派生類的更新隻能在UI線程,然而UI線程還同時處理其他交互邏輯,這就無法保證view更新的速度和幀率瞭,而SurfaceView可以用獨立的線程來進行繪制,因此可以提供更高的幀率,例如遊戲,攝像頭取景等場景就比較適合用SurfaceView來實現。
什麼是SurfaceHolder.Callback?
SurfaceHolder.Callback主要是當底層的Surface被創建、銷毀或者改變時提供回調通知,由於繪制必須在surface被創建後才能進行,因此SurfaceHolder.Callback中的surfaceCreated 和surfaceDestroyed 就成瞭繪圖處理代碼的邊界。SurfaceHolder,可以把它當成Surface的容器和控制器,用來操縱Surface。處理它的Canvas上畫的效果和動畫,控制表面,大小,像素等。

為什麼普通view隻能在UI線程刷新?

UI線程是最重要的線程,它既不能被阻塞,也不是線程安全的,如果你瞭解多線程操作的話,對於線程安全、同步鎖等等這樣的詞語應該不陌生,UI線程負責繪制界面和分發窗口事件,任務是非常之重,通常多線程處理時為瞭保證訪問資源的正確性,通常對於某些操作都會加上同步鎖,這樣會顯然會降低效率,而且還會涉及到線程的等待與線程上下文切換,為瞭提高效率,UI線程不在使用這些繁瑣的多線程機制,為瞭保證對UI操作的正確性,隻允許在UI線程中操作UI。在非UI線程中可通過post或者runOnUiThread來刷新view

其它的一些總結:

SurfaceView是視圖(View)的繼承類,這個視圖裡內嵌瞭一個專門用於繪制的Surface。你可以控制這個Surface的格式和尺寸。SurfaceView控制這個Surface的繪制位置。

Surface是縱深排序(Z-ordered)的,這表明它總在自己所在窗口的後面。Surfaceview提供瞭一個可見區域,隻有在這個可見區域內的Surface部分內容才可見,可見區域外的部分不可見。Surface的排版顯示受到視圖層級關系的影響,它的兄弟視圖結點會在頂端顯示。這意味者 Surface的內容會被它的兄弟視圖遮擋,這一特性可以用來放置遮蓋物(overlays)(例如,文本和按鈕等控件)。註意,如果Surface上面 有透明控件,那麼它的每次變化都會引起框架重新計算它和頂層控件的透明效果,這會影響性能。

你可以通過SurfaceHolder接口訪問這個Surface,getHolder()方法可以得到這個接口。

SurfaceView變得可見時,Surface被創建;SurfaceView隱藏前,Surface被銷毀。這樣能節省資源。如果你要查看Surface被創建和銷毀的時機,可以重載surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)。

SurfaceView的核心在於提供瞭兩個線程:UI線程和渲染線程。這裡應註意:  www.aiwalls.com

       1. 所有SurfaceView和SurfaceHolder.Callback的方法都應該在UI線程裡調用,一般來說就是應用程序主線程。渲染線程所要訪問的各種變量應該作同步處理

       2. 由於Surface可能被銷毀,它隻在SurfaceHolder.Callback.surfaceCreated()和SurfaceHolder.Callback.surfaceDestroyed()之間有效,所以要確保渲染線程訪問的是合法有效的Surface。

 作者:zjmdp

發佈留言