歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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

什麼是Surface?

簡單地說Surface對應了一塊屏幕緩沖區,每個window對應一個Surface,任何View都是畫在Surface上的,傳統的view共享一塊屏幕緩沖區,所有的繪制必須在UI線程中進行

什麼是SurfaceView?

說SurfaceView是一個View也許不夠嚴謹,然而從定義中 public class SurfaceView extends View {...}顯示SurfaceView確實是派生自View,但是SurfaceView卻有著自己的Surface,繼續看SurfaceView的源碼:

  1. if (mWindow == null) {  
  2.       mWindow = new MyWindow(this);  
  3.       mLayout.type = mWindowType;  
  4.       mLayout.gravity = Gravity.LEFT|Gravity.TOP;  
  5.       mSession.addWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,  
  6.       mVisible ? VISIBLE : GONE, mContentInsets);  
  7. }  

很明顯,每個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線程和渲染線程。這裡應注意:

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

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

以上總結基於網上的一些資料以及個人的理解,如有錯誤還請指正~

Copyright © Linux教程網 All Rights Reserved