2011-05-18 83 views
3

我正在爲Android開發一個小遊戲(測試),但我不明白用SurfaceView製作好線程的邏輯。lockCanvas上的NullPointerException()

我遇到了[SurfaceView對象] .getHolder()。lockCanvas(null)的問題。問題是lockCanvas返回一個無效值(在這種情況下爲null)。

我無法捕捉到這個異常,因爲我不能! :/

這是我的代碼:

package game; 

import game.logics.SceneGroup; 
import game.scenes.TeamScene; 
import java.util.Timer; 
import java.util.TimerTask; 
import android.app.Activity; 
import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.os.Bundle; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.Window; 
import android.view.WindowManager; 

// Definição da Atividade 
public class GameActivity extends Activity { 
    // Definição do Ambiente 
    public class GameSurface extends SurfaceView 
            implements SurfaceHolder.Callback { 
     public GameSurface(final Context context) { 
      super(context); 

      this.getHolder().addCallback(this); 
      this.setFocusable(true); 
     } 

     @Override 
     public void surfaceChanged(final SurfaceHolder arg0, 
         final int arg1, final int arg2, final int arg3) {} 

     @Override 
     public void surfaceCreated(final SurfaceHolder arg0) { 
      GameActivity.this.running = true; 
     } 

     @Override 
     public void surfaceDestroyed(final SurfaceHolder arg0) { 
      GameActivity.this.running = false; 
     } 

     public void update(final Canvas canvas) { 
      GameActivity.this.scenes.update(canvas); 
     } 
    } 

    class GameTask extends TimerTask { 
     @Override 
     public void run() { 
      if(GameActivity.this.running == false) { 
       return; 
      } 

      final SurfaceHolder holder = 
           GameActivity.this.surface.getHolder(); 

      Canvas canvas = null; 
      try { 
       canvas = holder.lockCanvas(); 
       canvas.drawColor(Color.BLACK); 

       synchronized(holder) { 
        GameActivity.this.surface.update(canvas); 
       } 
      } 
      finally { 
       if(canvas != null) { 
        holder.unlockCanvasAndPost(canvas); 
       } 
      } 
     } 
    } 

    private GameSurface  surface; 
    private SceneGroup  scenes; 

    private Timer   timer; 
    private TimerTask  task; 
    private boolean   running = false; 

    @Override 
    public void onCreate(final Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     this.requestWindowFeature(Window.FEATURE_NO_TITLE); 
     this.getWindow().setFlags(
          WindowManager.LayoutParams.FLAG_FULLSCREEN, 
      WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     // ### SOLVE: PROBLEM START HERE ### 
     this.surface = new GameSurface(this); 

     this.scenes = new SceneGroup(this); 
     this.scenes.add(new TeamScene(this)); 

     this.timer = new Timer(); 
     this.task = new GameTask(); 

     // ### SOLVE: PROBLEM END HERE ### 
     // ### Invalid new instance of GameSurface ### 
     this.setContentView(new GameSurface(this)); 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
     this.timer.cancel(); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     this.timer.scheduleAtFixedRate(this.task, 0, 33); 
    } 
} 

我做的對嗎? 我能做些什麼來修復我的代碼?

+0

我懷疑你的問題是你從非guid線程調用surface.getHolder()。將持有者保存在onCreate方法中,然後像訪問lockCanvas一樣訪問它,並查看是否有幫助。 – forsvarir 2011-05-18 20:05:12

+0

謝謝。但我已經嘗試過了,就像'this.surface = new GameSurface(this);/*然後*/this.holder = this.surface.getHolder();'但是不起作用。我的問題有更多的嫌疑犯? – 2011-05-18 20:14:44

+2

嗯...你知道你正在創建GameSurface兩次嗎?一個你分配給這個表面,第二個你傳遞給setContentView ......大概他們應該是同一個?!? – forsvarir 2011-05-18 20:33:01

回答

3

您正在創建GameSurface兩次。

一旦在這裏:

this.surface = new GameSurface(this); 

而且在這裏再次:

this.setContentView(new GameSurface(this)); 

想必他們應該是相同的嗎?