SurfaceView概述

jia635發表於2014-07-14

為什麼選擇SurfaceView

眾所周知,SurfaceView繼承自View,但它與View不同?View是在UI的主執行緒中更新畫面,而SurfaceView是在一個新執行緒中更新畫面。我們不可能寫一個方法讓主執行緒自己運動。View的特性決定了其不適合做動畫,因為如果更新畫面時間過長,那麼主UI執行緒就會被正在畫的函式阻塞。所以Android中通常用SurfaceView顯示動畫效果。

在對SurfaceView進行操作前Android為我們提供了一個十分好用的介面:SurfaceHolder.Callback介面。該介面中有三個抽象方法,這三個抽象方法是SurfaceView的三個生命週期:


abstract void            surfaceChanged(SurfaceHolder holder, int format, int width, int height)
This is called immediately after any structural changes (format or size) have been made to the surface.
abstract void    surfaceCreated(SurfaceHolder holder)
This is called immediately after the surface is first created.
abstract void    surfaceDestroyed(SurfaceHolder holder)
This is called immediately before a surface is being destroyed.

以上是從Api中我直接copy出來的,相信如果熟悉Activity的朋友我就不用過多進行解釋了(當然,如果不熟悉Acitvity,還是去看看吧)。

控制SurfaceView的SurfaceHolder

上一節的Surface概述中我曾經說過每一個Surface都有一個Canvas,而Surface自身控制自己的大小等等屬性。但是Surface是如何控制自己的呢?

在SurfaceView中一般通過使用SurfaceHolder類來控制Canvas在其surface上的操作。

得到SurfaceHolder

如何得到SurfaceHolder?其實很簡單,在SurfaceView中提供了getHolder()方法。如果該surfaceView中還需要實現回撥生命週期,那麼holder還需要呼叫addCallback()方法為其新增回撥宣告週期。API如下:

abstract void            addCallback(SurfaceHolder.Callback callback)
Add a Callback interface for this holder.

SurfaceHolder中還有幾個十分重要的方法:

lockCanvas():該方法用於鎖定畫布,這樣Surface中就可以指定back buffer中的畫布是那一塊了。之後就可以在畫布上進行繪畫,該方法的API如下,

abstract Canvas      lockCanvas()
Start editing the pixels in the surface.


lockCanvas()方法是對整個Surface進行重繪,但是很多情況下,我們只需要對Surface的一小部分進行重畫時,則使用lockCanvas(Rect dirty)更為明智。

lockCanvas(Rect dirty)通過其中的引數也可以看出,其只更新Rect部分的畫面。API入下:

abstract Canvas      lockCanvas(Rect dirty)
Just like lockCanvas() but allows to specify a dirty rectangle.

以上兩個方法是對Canvas進行鎖定,當Canvas繪製完畢之後,Surface的front buffer就需要這個Surface進行顯示。如果此時Canvas還在鎖定狀態,則Surface的front buffer將不能得到Canvas。所以此時應該在canvas繪畫完畢之後,釋放鎖定。

unlockCanvasAndPost(Canvas canvas):用於釋放出於鎖定狀態的Canvas。API如下:

以上兩個方法是對Canvas進行鎖定,當Canvas繪製完畢之後,Surface的front buffer就需要這個Surface進行顯示。如果此時Canvas還在鎖定狀態,則Surface的front buffer將不能得到Canvas。所以此時應該在canvas繪畫完畢之後,釋放鎖定。

unlockCanvasAndPost(Canvas canvas):用於釋放出於鎖定狀態的Canvas。API如下:

abstract void            unlockCanvasAndPost(Canvas canvas)
Finish editing pixels in the surface.




相關文章