2013-03-01 60 views
1

我正在爲Android的遊戲工作,當我關閉應用程序它崩潰。我認爲這是因爲我正在使用空畫布進行渲染。當我做一個空檢查時,程序不會崩潰,但它在關閉後不會重新打開。這裏是我的線程的run:Android應用沒有響應時關閉

public void run() { 
    Canvas canvas; 
    Log.d(TAG, "Starting game loop"); 

    long beginTime;  // the time when the cycle begun 
    long timeDiff;  // the time it took for the cycle to execute 
    int sleepTime;  // ms to sleep (<0 if we're behind) 
    int framesSkipped; // number of frames being skipped 

    sleepTime = 0; 

    while (running) { 
     canvas = null; 
     // try locking the canvas for exclusive pixel editing 
     // in the surface 
     try { 
      canvas = this.surfaceHolder.lockCanvas(); 
      synchronized (surfaceHolder) { 
       beginTime = System.currentTimeMillis(); 
       framesSkipped = 0; // resetting the frames skipped 
       // update game state 
       this.gamePanel.update(); 
       // render state to the screen 
       // draws the canvas on the panel 
       this.gamePanel.render(canvas);    
       // calculate how long did the cycle take 
       timeDiff = System.currentTimeMillis() - beginTime; 
       // calculate sleep time 
       sleepTime = (int)(FRAME_PERIOD - timeDiff); 

       if (sleepTime > 0) { 
        // if sleepTime > 0 we're OK 
        try { 
         // send the thread to sleep for a short period 
         // very useful for battery saving 
         Thread.sleep(sleepTime);  
        } catch (InterruptedException e) {} 
       } 

       while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) { 
        // we need to catch up 
        this.gamePanel.update(); // update without rendering 
        sleepTime += FRAME_PERIOD; // add frame period to check if in next frame 
        framesSkipped++; 
       } 
      } 
     } finally { 
      // in case of an exception the surface is not left in 
      // an inconsistent state 
      if (canvas != null) { 
       surfaceHolder.unlockCanvasAndPost(canvas); 
      } 
     } // end finally 
    } 
} 

,這裏是在面類relavent方法。

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 
} 


@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    // at this point the surface is created and 
    // we can safely start the game loop 
    thread.setRunning(true); 
    thread.start(); 
} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    Log.d(TAG, "Surface is being destroyed"); 
    // tell the thread to shut down and wait for it to finish 
    // this is a clean shutdown 
    boolean retry = true; 
    while (retry) { 
     try { 
      thread.setRunning(false); 
      thread.join(); 
      retry = false; 
     } catch (InterruptedException e) { 
      // try again shutting down the thread 
     } 
    } 
    Log.d(TAG, "Thread was shut down cleanly"); 
} 

空檢查是否正確,我錯過了恢復活動的方法?

logcat的時候nullcheck不到位:

03-01 10:37:19.557: E/AndroidRuntime(25129): FATAL EXCEPTION: Thread-16380 
03-01 10:37:19.557: E/AndroidRuntime(25129): java.lang.NullPointerException 
03-01 10:37:19.557: E/AndroidRuntime(25129): at org.awesome.AndroidGame.MainGamePanel.render(MainGamePanel.java:192) 
03-01 10:37:19.557: E/AndroidRuntime(25129): at org.awesome.AndroidGame.MainThread.run(MainThread.java:73) 
03-01 10:37:23.357: E/BitmapFactory(25280): Unable to decode stream: java.io.FileNotFoundException: /level_1_1.png: open failed: ENOENT (No such file or directory) 
03-01 10:37:36.097: E/AndroidRuntime(25280): FATAL EXCEPTION: Thread-16395 
03-01 10:37:36.097: E/AndroidRuntime(25280): java.lang.NullPointerException 
03-01 10:37:36.097: E/AndroidRuntime(25280): at org.awesome.AndroidGame.MainGamePanel.render(MainGamePanel.java:192) 
03-01 10:37:36.097: E/AndroidRuntime(25280): at org.awesome.AndroidGame.MainThread.run(MainThread.java:73) 
03-01 11:02:49.227: E/AndroidRuntime(26150): FATAL EXCEPTION: Thread-16425 
03-01 11:02:49.227: E/AndroidRuntime(26150): java.lang.NullPointerException 
03-01 11:02:49.227: E/AndroidRuntime(26150): at org.awesome.AndroidGame.MainGamePanel.render(MainGamePanel.java:192) 
03-01 11:02:49.227: E/AndroidRuntime(26150): at org.awesome.AndroidGame.MainThread.run(MainThread.java:73) 
03-01 11:02:53.717: E/AndroidRuntime(26177): FATAL EXCEPTION: Thread-16428 
03-01 11:02:53.717: E/AndroidRuntime(26177): java.lang.NullPointerException 
03-01 11:02:53.717: E/AndroidRuntime(26177): at org.awesome.AndroidGame.MainGamePanel.render(MainGamePanel.java:192) 
03-01 11:02:53.717: E/AndroidRuntime(26177): at org.awesome.AndroidGame.MainThread.run(MainThread.java:73) 

logcat的時候nullcheck到位:

03-01 11:58:50.297: E/AndroidRuntime(32292): FATAL EXCEPTION: main 
03-01 11:58:50.297: E/AndroidRuntime(32292): java.lang.IllegalThreadStateException: Thread already started. 
03-01 11:58:50.297: E/AndroidRuntime(32292): at java.lang.Thread.start(Thread.java:1045) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at org.awesome.AndroidGame.MainGamePanel.surfaceCreated(MainGamePanel.java:83) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.SurfaceView.updateWindow(SurfaceView.java:569) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:231) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.View.dispatchWindowVisibilityChanged(View.java:7537) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1039) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1039) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1039) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1211) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.Choreographer.doCallbacks(Choreographer.java:562) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.Choreographer.doFrame(Choreographer.java:532) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.os.Handler.handleCallback(Handler.java:725) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.os.Handler.dispatchMessage(Handler.java:92) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.os.Looper.loop(Looper.java:137) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at android.app.ActivityThread.main(ActivityThread.java:5039) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at java.lang.reflect.Method.invokeNative(Native Method) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at java.lang.reflect.Method.invoke(Method.java:511) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 
03-01 11:58:50.297: E/AndroidRuntime(32292): at dalvik.system.NativeStart.main(Native Method) 
+0

當你說「關閉應用程序」時,是指點擊後退按鈕,點擊主頁按鈕,還是在代碼中提供了自定義退出功能? – 2013-03-01 18:54:31

+0

這兩個按鈕都會使我的應用程序崩潰,但我正在專門討論主頁按鈕。 – ceptno 2013-03-01 19:03:48

+1

LogCat的堆棧跟蹤是否指向特定的代碼行? – 2013-03-01 19:07:09

回答

0

在你開始你的線程我相信你應該檢查一下看它是否已經存在。

這是我的理解,你不能重新啓動Android的線程,所以你應該檢查,看看它以前就存在,如果它沒有,開始一個新的,像這樣:

if(thread.getState()==Thread.State.TERMINATED){   //Exists?   
thread = new Thread(holder, context, handler);}   //Re-Create 

thread.setRunning(true); 
    thread.start(); 

由於對於空畫布,如果您的意思是在您的run方法(主要是w'hile循環)中對null進行檢查,那麼在您解鎖和postpost之前的「finally」部分中,是的這是正確的。

但是我有一種感覺,你不是這個檢查。當我按下後退鍵時出現類似的問題,出於某種原因,Null Canvas被間斷性地傳遞給我的onDraw/Render方法。實際上,我必須將整個代碼封裝在空畫布的檢查中,因此只有在檢查回來時纔會呈現負面效果!它的工作,並在此之後是完全穩定。

如果我沒有記錯的話,經過大量的互聯網研究,看起來這是幾個人的問題。