2013-03-01 61 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方法。实际上,我必须将整个代码封装在空画布的检查中,因此只有在检查回来时才会呈现负面效果!它的工作,并在此之后是完全稳定。

如果我没有记错的话,经过大量的互联网研究,看起来这是几个人的问题。