Android surfaceview詳解(一)
surface,這個單詞的意思是浮在表面的,那麼surfaceview就是浮在表面的view了。如果真的這樣解釋,估計有人要拍磚了。然而,話雖不能這麼說,取這個名兒,多少還是有點關系的。surface是一個可見區域。
我們在屏幕上看到的這些view,在屏幕上看到的就是畫面,在內存中就是一塊內存區。繪圖的時候,就是顯示的硬件如顯卡將內存區的這塊圖形數據繪制到屏幕上。所以,從內存的角度去看這些東西,會比較好理解。
surface是surfaceview中的一個可見部分。我們知道,我們看到的屏幕上的圖形,是二維的,我們看到的就是長和寬,其實,在內部實際上是三維的,另一個維度,就是層layer。我們用visio繪圖,都會看到這種情況,一個圖形會將另個圖形遮住,是因為這個圖形在上層。如果有同AutoCAD的經驗,對這個更容易理解。我們看到的圖形實際上是很多圖形一層層的疊加在一起的,這些圖形元素完全不可見,或者部分可見部分不可見,或者完全可見。
這樣看來,surface就可以這樣理解:它是內存中一塊區域,它是surfaceview可見不那個部分,繪圖操作作用於它,然後它就會被顯卡之類的顯示控制器繪制到屏幕上。
surface是個啥,大概已經有了些概念了。因為它對應了一個內存區,大家都知道,內存區的對象是有生命周期的,可以動態的申請創建和銷毀,當然也可能會更新。於是,就有了作用於這個內存區的操作,這些操作就是surfaceCreated/Changed/Destroyed。三個操作放在一起,就是callback,所以在很多例子裡看到,會有callback。
callback,是回調,意思是自己能干一些活,不過自己不去主動做,而是到別人那裡去登記一下,別人需要的時候,就會叫我去做。就這個例子而言,可以打這個比方,某建築工人隊伍A,能蓋房子,能裝修,也能拆房子。可是他自己不去主動的做這些事情,而是去向開發商B去登記這三種能力,當然了,他把這三種能力打了包,叫做A的能力。啥時候,B有活干了,就叫A去做,或者是蓋房子,或者是裝修,或者是拆建築。在這個例子中,能力包就是callback.
說了這個例子,其實就解釋了 surface相關的一些東西,callback已經說過了,下面來說說其他的。假設surface就是一棟房子,那麼surface擁有surfaceHolder,誰呢?在這個例子中好比建築隊A。蓋房子對應的就是surfaceCreated, 拆房子就對應了surfaceDestroyed,裝修就對應了surfaceChanged.
surface有生存期,好比房子有生存期,在建造以後就存在,在拆了之後就沒有了。裝修必須發生在這之間。同樣的,surface的change必須發生在created和destroyed之間。
surfaceview知道surface的holder是誰,在surfaceview生成的時候,會調用getHolder得到holder,然後holder會調用addCallback將三個callback函數注冊。
holder擁有對於surface的控制權。在很多程序中,會在surfaceCreated的函數實現中創建另一個線程。所以在這裡有兩個線程,一個是UI線程,另一個負責畫圖的線程。畫圖線程由UI線程調用surfaceCreated的時候創建,在surfaceDestroyed調用的時候放回到線程池。在這中間,畫圖線程負責圖形的繪制。
在這種模型下,UI線程和畫圖線程各司其職,前者主要負責和用戶的交互,而後者,在負責繪制圖形。這樣,繪制圖形的時候如果時間較長,不會阻塞用戶的輸入。
我們知道,線程共享內存數據,所以, surface對於兩個線程是共享的。所以,為了避免在畫圖的時候,UI線程也對surface進行操作,在畫圖前,需要對surface加鎖。這個工作是有holder干的,holder會先鎖住surface中的一塊holder.lockCanvas,我們叫canvas,然後,在上面繪畫,畫完之後,會解鎖unlockCanvasAndPost。
在 應用中,畫圖可以是一次性的,也可以是由定時器觸發的定時的畫。實現的都是runnable類中的run方法。關於runnable類,這個Java中定義的,並不是android獨有的,可以參考Java的referrence.
這個模型最大的好處就是,畫圖不依賴於UI線程,不會阻塞UI線程。而單純的view是依賴於UI線程畫圖的。對於完全依賴於用戶的輸入進行圖像顯示的更新的,用view是可以的,但是如果能夠自動的進行繪圖,而不需等待用戶的輸入,surfaceview無疑是更好的選擇。
請看圖