2013-03-21 48 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(); 
} 

我希望这可以帮助别人。