2011-05-18 55 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)); 

想必他们应该是相同的吗?