2013-03-21 86 views
2

我想用SurfaceView開發一款遊戲。問題是,當我用surfaceDestroyed()方法銷燬thread時,應用程序在thread.join()中停止,但如果不用 在onDraw()中繪製畫布(canvas.drawColor(Color.GREEN);),則一切正常。 如何繪製畫布並致電thread.join()Android SurfaceView onDraw暫停Thread.join()

(我從互聯網上測試了許多例如遊戲,他們都有同樣的問題,當你打例如回去按鈕,你會得到一個FATAL EXCEPTION因爲thread仍在運行)

下面是代碼儘可能簡單。 謝謝

public class GameView extends SurfaceView implements SurfaceHolder.Callback { 

    private SurfaceHolder holder; 
    private GameLoopThread gameLoopThread; 

    public GameView(Context context) { 
     super(context); 
     holder = getHolder(); 
     holder.addCallback(this); 
    } 

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

    @Override 
    public void surfaceCreated(SurfaceHolder arg0) { 
     if (gameLoopThread == null) { 
      gameLoopThread = new GameLoopThread(this); 
      gameLoopThread.setRunning(true); 
      gameLoopThread.start(); 
      Log.e("thread", "iniciado"); 
     } 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder arg0) { 
     gameLoopThread.setRunning(false); 
     boolean retry = true; 
     while (retry) { 
      try { 
       gameLoopThread.join(); 
       retry = false; 
      } catch (InterruptedException e) { 
      } 
     } 
     Log.e("thread", "finalizado"); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     canvas.drawColor(Color.GREEN); 
    } 

    public static class GameLoopThread extends Thread { 
     private static final int FPS = 20; 
     private GameView view; 
     private boolean running; 

     public GameLoopThread(GameViwe gameView) { 
      this.view = gameView; 
     } 

     public void setRunning(boolean run) { 
      running = run; 
     } 

     @Override 
     public void run() { 
      long ticksPS = 1000/FPS; 
      long startTime; 
      long sleepTime; 
      while (running) { 
       Canvas c = null; 
       startTime = System.currentTimeMillis(); 
       try { 
        c = view.getHolder().lockCanvas(); 
        synchronized (view.getHolder()) { 
         view.onDraw(c); 
        } 
       } finally { 
        if (c != null) { 
         view.getHolder().unlockCanvasAndPost(c); 
        } 
       } 
       sleepTime = ticksPS - (System.currentTimeMillis() - startTime); 
       try { 
        if (sleepTime > 0) 
         sleep(sleepTime); 
        else 
         sleep(10); 
       } catch (Exception e) { 
       } 
      } 
     } 
    } 
} 

回答

0

所以我給了這個問題的解決辦法是改變的地方說:

try { 
    c = view.getHolder().lockCanvas(); 
    synchronized (view.getHolder()) { 
     view.onDraw(c); 
    } 
    } finally { 
     if (c != null) { 
      view.getHolder().unlockCanvasAndPost(c); 
     } 
} 

在GameLoopThread類與run()方法:

try { 
    c = view.getHolder().lockCanvas(); 
    synchronized (view.getHolder()) { 
     if(c != null) 
      view.onDraw(c); 
    } 
    } finally { 
     if (c != null) { 
      view.getHolder().unlockCanvasAndPost(c); 
     } 
} 

要完成此活動並致電另一個,我添加了一個名爲GameOver的方法,該方法效果很好:

private void GameOver() { 
    gameLoopThread.setRunning(false); 
    Context c = getContext(); 
    c.startActivity(intent); //intent must be declared 
    ((Activity) Pruebas.this.getContext()).finish(); 
} 

我希望這可以幫助別人。