2012年7月9日 星期一

【Android遊戲開發之三】剖析 SurfaceView ! Callback以及SurfaceHolder!!


各位童鞋請你們注意:surfaceview中確實有 onDraw這個方法,但是你surfaceview不會自己去調用!!!



    而我代碼中的ondraw() 也好 draw() 也好,都是我自己定義的一個方法。。。放在執行緒中不斷調用的,一定要注意!!



    之前我們對viewsurfaceview 做了比較和取捨,最後我們發現surfaceview更加的適合運作與遊戲開發中,那麼下面就讓我們來看看這個surfaceview的結構吧;



先上一段代碼:


  • /**
  • *
  • */
  • package com.himi;
  • import android.content.Context;
  • import android.graphics.Canvas;
  • import android.graphics.Color;
  • import android.graphics.Paint;
  • import android.view.SurfaceHolder;
  • import android.view.SurfaceView;
  • import android.view.SurfaceHolder.Callback;
  • import android.view.animation.Animation;
  • /**
  • * @author Himi
  • */
  • public class MySurfaceView extends SurfaceView implements Callback, Runnable {// 备注1
  • private SurfaceHolder sfh;
  • private Thread th;
  • private Canvas canvas;
  • private Paint paint;
  • private int ScreenW, ScreenH;
  • public MySurfaceView(Context context) {
  • super(context);
  • th = new Thread(this);
  • sfh = this.getHolder();
  • sfh.addCallback(this); // 备注1
  • paint = new Paint();
  • paint.setAntiAlias(true);
  • paint.setColor(Color.RED);
  • this.setKeepScreenOn(true);// 保持屏幕常亮
  • }
  • @Override
  • public void startAnimation(Animation animation) {
  • super.startAnimation(animation);
  • }
  • public void surfaceCreated(SurfaceHolder holder) {
  • ScreenW = this.getWidth();// 备注2
  • ScreenH = this.getHeight();
  • th.start();
  • }
  • private void draw() {
  • try {
  • canvas = sfh.lockCanvas(); // 得到一个canvas实例
  • canvas.drawColor(Color.WHITE);// 刷屏
  • canvas.drawText("Himi", 100, 100, paint);// 画文字文本
  • canvas.drawText("这就是简单的一个游戏框架", 100, 130, paint);
  • } catch (Exception ex) {
  • } finally { // 备注3
  • if (canvas != null)
  • sfh.unlockCanvasAndPost(canvas); // 将画好的画布提交
  • }
  • }
  • public void run() {
  • while (true) {
  • draw();
  • try {
  • Thread.sleep(100);
  • } catch (InterruptedException e) {
  • // TODO Auto-generated catch block
  • e.printStackTrace();
  • }
  • }
  • }
  • public void surfaceChanged(SurfaceHolder holder, int format, int width,
  • int height) {
  • }
  • public void surfaceDestroyed(SurfaceHolder holder) {
  • // TODO Auto-generated method stub
  • }
  • }


  • 代碼很簡單,我們繼承繼承surfaceview類,並且使用回檔callback介面以及執行緒runnable介面。那麼這裡我簡單的說下Callback介面和SurfaceHolder 類的作用;



    //備註1



    callback介面:



        只要繼承SurfaceView類並實現SurfaceHolder.Callback介面就可以實現一個自訂的SurfaceView了,SurfaceHolder.Callback在底層的Surface狀態發生變化的時候通知ViewSurfaceHolder.Callback具有如下的介面:



        surfaceCreated(SurfaceHolder holder):當Surface第一次創建後會立即調用該函數。程式可以在該函數中做些和繪製介面相關的初始化工作,一般情況下都是在另外的執行緒來繪製介面,所以不要在這個函數中繪製Surface



         surfaceChanged(SurfaceHolder holder, int format, int width,int height):當Surface的狀態(大小和格式)發生變化的時候會調用該函數,在surfaceCreated調用後該函數至少會被調用一次。



     SurfaceHolder 類:



        它是一個用於控制surface的介面,它提供了控制surface 的大小,格式,上面的圖元,即監視其改變的。



        SurfaceViewgetHolder()函數可以獲取SurfaceHolder物件,Surface 就在SurfaceHolder物件內。雖然Surface保存了當前視窗的圖元資料,但是在使用過程中是不直接和Surface打交道的,由SurfaceHolderCanvas lockCanvas()或則Canvas lockCanvas()函數來獲取Canvas物件,通過在Canvas上繪製內容來修改Surface中的資料。如果Surface不可編輯或則尚未創建調用該函數會返回null,在 unlockCanvas() lockCanvas()Surface的內容是不緩存的,所以需要完全重繪Surface的內容,為了提高效率只重繪變化的部分則可以調用lockCanvas(Rect rect)函數來指定一個rect區域,這樣該區域外的內容會緩存起來。在調用lockCanvas函數獲取Canvas後,SurfaceView會獲取Surface的一個同步鎖直到調用unlockCanvasAndPost(Canvas canvas)函數才釋放該鎖,這裡的同步機制保證在Surface繪製過程中不會被改變(被摧毀、修改)。



    // 備註2



        我沒有在該surfaceview的初始化函數中將其 ScreenW ScreenH 進行賦值,這裡要特別注意,如果你在初始化調用ScreenW = this.getWidth();ScreenH = this.getHeight();那麼你將得到很失望的值 全部為0;原因是和介面Callback介面機制有關,當我們繼承callback介面會重寫它的surfaceChanged()surfaceCreated()surfaceDestroyed(),這幾個函數當surfaceCreated()被執行的時候,真正的view才被創建,也就是說之前得到的值為0 ,是因為初始化會在surfaceCreated()方法執行以前執行,view沒有的時候我們去取螢幕寬高肯定是0,所以這裡要注意這一點; 



    //備註3



        這裡我把draw的代碼都try起來,主要是為了當畫的內容中一旦拋出異常了,那麼我們也能 finally中執行該操作。這樣當代碼拋出異常的時候不會導致Surface出去不一致的狀態。 



        其實這就是一個簡單的遊戲架構了,當然還少了按鍵處理,聲音播放等等,這些我後續會寫出相關的學習文章。對於surfaceview的介紹差不多就介紹到這裡了,其中的理解是看了別人的文章和自己的理解、當然可能理解的會有些偏差,但是我想不會太離譜 呵呵。

    沒有留言:

    張貼留言