Android SurfaceView 詳解(二)

說一下自己關於SurfaceView的一點感受:

(1.)定義:
    可以直接從內存或者DMA等硬件接口取得圖像數據,是個非常重要的繪圖容器。
    它的特性:可以在主線程之外的線程中向屏幕繪圖上。這樣可以避免畫圖任務繁重時造成主線程阻塞,從而提高瞭程序的反應速度。在遊戲開發中多用到SurfaceView,遊戲中的背景、人物、動畫等等盡量在畫佈canvas中畫出。
   SurfaceView提供直接訪問一個可畫圖的界面,可以控制在界面頂部的子視圖層。SurfaceView是提供給需要直接畫像素而不是使用窗體不見的應用使用的。Android系統中一個重要的概念和線索是Surface.View及其子類(TextView,Button等)要畫在Surface上。每個Surface創建一個Canvas對象(但屬性時常改變),用來管理view在Surface上的繪圖操作,如畫點畫線,使用它是,一般都是出現在

最頂層。
  (2.)實現
  首先繼承SurfaceView並實現SurfaceHolder.Callback接口
  使用接口的原因:因為使用SurfaceView有一個原則,所有的繪圖工作必須得在Surface被創建之後才能開始(Surface可以當作顯存的一個映射,寫入到Surface的內容,可以被直接復制到顯存中從而顯示出來,這使得顯示的速度會非常快),而在Surface被銷毀之前必須結束。所以CallBack中的surfaceCreated和surfaceDestroyed就成瞭繪圖代理代碼的邊界。
   需要重寫的方法:
   a. public void sufaceChanged(SurfaceHolder holder,int format,int width,int height){}//Surface的大小發生改變時調用
   b. public void surfaceCreated(SurfaceHolder holder){}//Surface創建時激發,一般在這裡調用畫面的線程。
   c. public void surfaceDestroyed(SurfaceHolder holder){}//銷毀時激發,一般在這裡將畫面的線程停止、釋放。
   d. public void addCallback{};//給SurfaceView添加一個回調函數。
   e. public void lockCanvas{};//鎖定畫佈。繪圖之前必須鎖定畫佈才能夠得到畫佈對象。
   f. public void unlockCanvasAndPost{};//開始繪制時鎖定瞭畫佈,繪制完成後解鎖畫佈。
   g. public void removeCallback:從SurfaceView中移除回調函數。

  SurfaceView不同View之處在於,SurfaceView不需要通過線程來更新視圖,但是再繪制前需要使用locakCanvas鎖定畫佈,並且得到畫佈,然後再畫佈上繪制你需要的圖像。繪制完成後需要使用lockCanvasAndPost方法來解鎖畫佈。於是才能顯示在屏幕上。事件的處理規則和View是一樣的。
 

 整個實現過程:

繼承SurfaceView並實現SurfaceHolder.Callback接口——>SurfaceView.getHolder()獲得SurfaceHolder對象—–>SurfaceHolder.addCallback(callback)添加回調函數—–>
  surfaceHolder.lockCanvas()獲得Canvas對象並鎖定畫佈——>Canvas繪畫——->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)結束鎖定畫圖,並提交改變,將圖形顯示。
 (3.)SurfaceHolder:
   這裡用到瞭一個類SurfaceHolder,可以把它當成surface的控制器,用來操縱surface。處理它的Canvas上畫的效果和動畫,控制表面,大小,像素等。
   幾個常用的方法:
   a.abstract void addCallback(SurfaceHolder.Callbask callback);//給SurfaceView當前的持有者一個回調函數。
   b.abstract Canvas lockCanvas();//鎖定畫佈,一般在鎖定後就可以通過其返回的畫佈對象Canvas,在其上面等操縱瞭。
   c.abstract Canvas lockCanvas(Rect dirty);//鎖定畫佈的某個區域進行畫圖等..因為畫完圖後,會調用下面的unlockCanvasAndPost()來改變顯示的內容。相對部分內存要求比較高的遊戲來說,  可以不用重畫dirty外的其他區域的像素,可以提高速度。
   d.abstract void unlockCanvasAndPost(Canvas canvas);//結束鎖定畫圖,並提交改變。

  最後通過一個SurfaceView開發一個示波器的例子,來結束SurfaceView吧(代碼太多,放在下一篇博文中),謝謝

 

 

摘自 Damon_tong的專欄

發佈留言