2013-03-01 3 views
1

Android 용 게임을하고 있는데 앱을 닫으면 충돌이 발생합니다. 나는 널 캔버스로 렌더링을하고 있기 때문에 이것이라고 생각한다. null 체크를하면 프로그램이 중단되지 않지만 프로그램을 닫은 후에는 다시 열리지 않습니다. 여기 내 스레드가 실행됩니다 :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"); 
} 

null 체크가 정확하고 방금 활동을 다시 시작하는 방법이 누락 되었습니까?

로그 캣 nullcheck이 발생하지 않을 때 : 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) 

로그 캣 :

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

"앱 닫기"라고 말하면 뒤로 버튼을 누르거나, 집 버튼을 누르거나, 코드에서 맞춤 이탈 기능을 제공 했습니까? –

+0

두 버튼 모두 내 응용 프로그램을 충돌하지만 홈 버튼에 관해 구체적으로 이야기하고있었습니다. – ceptno

+1

LogCat의 stacktrace가 특정 코드 행을 가리 킵니까? –

답변

0

당신이 당신의 스레드를 시작하기 전에 나는 이미 존재하는 경우 당신이 그것을보고 확인해야합니다 생각 .

그것은 당신이 안드로이드에서 스레드를 다시 시작할 수 없습니다 나의 이해, 그래서 당신은 이전에 존재하는지 확인해야하며 그렇게한다면, 그래서 같은 새로운 시작 :

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

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

로를 널 캔버스의 경우 run 메소드 (main w'hile 루프)에서 null에 대한 검사를 의미하는 경우 unlockandpost를 수행하기 전에 'finally'섹션에서 네, 맞습니다.

그러나 나는이 수표를 의미하지 않는다고 생각합니다. 나는 뒤로 키를 눌렀을 때 비슷한 이유로 문제가 발생했다. 왜냐하면 어떤 이유에서 Null Canvas가 onDraw/Render 메서드에 간헐적으로 전달되고 있었기 때문이다. 실제로 null canvas에 대한 체크 내에서 그 메소드의 전체 코드를 캡슐화해야했기 때문에 체크가 부정적으로 돌아 왔을 때만 렌더링됩니다! 그것은 효과가 있었고 그 후 완벽하게 안정적이었습니다.

인터넷에서 많은 연구가 끝난 후 올바르게 기억하는 경우 이는 몇 사람이 가지고 있었던 문제인 것으로 보입니다.

관련 문제