Surface與SurfaceView、SurfaceHolder

什麼是Surface?html

  android API的解釋是:Handle onto a raw buffer that is being managed by the screen compositorandroid

Surface對應了一塊屏幕的緩衝區,每個window對應一個Surface,任何View都是畫在Surface上的,傳統的view共享一塊屏幕緩衝區,全部的繪製都必須在UI線程上進行。編程

什麼是SurfaceViewcanvas

  SurfaceView的API中文翻譯:api

  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。框架

  SurfaceView繼承與View每個SurfaceView建立的時候都會建立一個Window將自身與window綁定在一塊兒,因此SurfaceView內嵌了一個本身的Surface,傳統的view以及派生類的更新只能在UI線程,而後UI線程同時還處理着其餘交互邏輯,這就沒法保證view更新的速度與幀率了,而SurfaceView能夠用獨立線程來繪製,所以能夠得到更高的幀率。函數

什麼是SurfaceHolder性能

  API:Abstract interface to someone holding a display surface. Allows you to control the surface size and format, edit the pixels in the surface, and monitor changes to the surface. This interface is typically available through the SurfaceView class.動畫

  這是一個接口要經過SurfaceView來實現對Surface的控制,改變尺寸,格式等等。spa

拾人牙慧

一、定義

  能夠直接從內存或者DMA等硬件接口取得圖像數據,是個很是重要的繪圖容器,這裏與api23之後出現的TextureView不一樣。

  它的特性是:能夠在主線程以外的線程中向屏幕繪圖上。這樣能夠避免畫圖任務繁重的時候形成主線程阻塞,從而提升了程序的反應速度。在遊戲開發中多用到SurfaceView,遊戲中的背景、人物、動畫等等儘可能在畫布canvas中畫出。

二、實現

  首先繼承SurfaceView並實現SurfaceHolder.Callback接口
  使用接口的緣由:由於使用SurfaceView 有一個原則,全部的繪圖工做必須得在Surface 被建立以後才能開始(Surface—表面,這個概念在 圖形編程中經常被提到。基本上咱們能夠把它看成顯存的一個映射,寫入到Surface 的內容
                      能夠被直接複製到顯存從而顯示出來,這使得顯示速度會很是快),而在Surface 被銷燬以前必須結束。因此Callback 中的surfaceCreated 和surfaceDestroyed 就成了繪圖處理代碼的邊界。

須要重寫的方法

   (1)public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}

     //在surface的大小發生改變時激發

 (2)public void surfaceCreated(SurfaceHolder holder){}

     //在建立時激發,通常在這裏調用畫圖的線程。

 (3)public void surfaceDestroyed(SurfaceHolder holder) {}

     //銷燬時激發,通常在這裏將畫圖的線程中止、釋放。

整個過程:繼承SurfaceView並實現SurfaceHolder.Callback接口 ----> SurfaceView.getHolder()得到SurfaceHolder對象 ---->SurfaceHolder.addCallback(callback

)添加回調函數---->SurfaceHolder.lockCanvas()得到Canvas對象並鎖定畫布----> Canvas繪畫 ---->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)結束鎖定畫圖,並提交改變,將圖形顯示。

 這裏lockCanvas-->unclockCanvasAndPost過程要在一個單獨的線程裏繪畫。

 

在SurfaceHolder源碼裏面有有一個函數getSurface(),有這麼一段解釋:

* Direct access to the surface object.  The Surface may not always be
* available -- for example when using a {@link SurfaceView} the holder's
* Surface is not created until the view has been attached to the window
* manager and performed a layout in order to determine the dimensions
* and screen position of the Surface. You will thus usually need
* to implement {@link Callback#surfaceCreated Callback.surfaceCreated}
* to find out when the Surface is available for
use.

綜上所述我的的的理解,一個window都有一個Surface緩衝區,將要顯示的數據直接丟進去就能夠顯示,而SurfaceView是爲了得到更高的頻率與幀率而不與UI線程性能衝突,因此單獨有一個線程來處理繪圖,所以它也有一塊獨立的Surface區,而SurfaceHolder看名字就知道,是能夠對Surface進行各類操做的,具體底層怎麼實現是api的工做,咱們只要知道它是的功能,而SurfaceHolder與Surface怎麼關聯的呢,這裏的英文解釋的很好。這個函數就是得到Surface的直接接口,可是Surface不是一直均可用,當使用SurfaceView的時候一直到surfaceCreated(..)函數調用以前都是不可用的,所以我在現實圖像的時候要在surfaceCreated(..)函數調用之後啓動畫圖線程,或者在在調用Camera的時候要在這個函數裏傳入Holder給Camera才能正確的將圖像數據傳入到Surface,固然若是推出程序,SurfaceDestroy(..)中釋放資源。
相關文章
相關標籤/搜索