Android应用没有响应时关闭
问题描述:
我正在为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)
答
在你开始你的线程我相信你应该检查一下看它是否已经存在。
这是我的理解,你不能重新启动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方法。实际上,我必须将整个代码封装在空画布的检查中,因此只有在检查回来时才会呈现负面效果!它的工作,并在此之后是完全稳定。
如果我没有记错的话,经过大量的互联网研究,看起来这是几个人的问题。
当你说“关闭应用程序”时,是指点击后退按钮,点击主页按钮,还是在代码中提供了自定义退出功能? – 2013-03-01 18:54:31
这两个按钮都会使我的应用程序崩溃,但我正在专门讨论主页按钮。 – ceptno 2013-03-01 19:03:48
LogCat的堆栈跟踪是否指向特定的代码行? – 2013-03-01 19:07:09