android surfaceview在转到后台时崩溃了

时间:2011-10-21 13:55:49

标签: android surfaceview

当Surfaceview通过接听电话或退出并返回应用程序进入后台时,我的应用程序崩溃了。我读到,在这些情况下,surfacedestroyed并没有接到电话 给出的解决方案对我没有用。 如果有人可以帮我处理我的代码,我将不胜感激。 感谢

public GameLoopThread(GameView view)
{

this.view=view;
}
public void setRunning (boolean run)
{
    running=run;
}
@Override
public void run() {

    long ticksPerSecond=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);
        }

        } catch (Exception e) {
            // TODO: handle exception
        }
        finally{
            if(c!=null)
            view.getHolder().unlockCanvasAndPost(c);
        }
        sleepTime=ticksPerSecond-(System.currentTimeMillis()-startTime);
        try
        {if(sleepTime>0)
            sleep(sleepTime);
        else
            sleep(10);

        }
        catch(Exception e){}

        synchronized (mPauseLock) {
            while (!running) {
                try {
                    mPauseLock.wait();
                } catch (InterruptedException e) {
                }
            }
        }
    }

and in the surfaceview:
 public void surfaceDestroyed(SurfaceHolder holder) {
 if(gameLoopThread.isAlive())
            {
                boolean retry = true;
                gameLoopThread.setRunning(false);
                while (retry) {
                    try {
                        gameLoopThread.join();
                        retry = false;
                    } catch (InterruptedException e) {
                    }
                }
            }
            }

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                if(!gameLoopThread.isAlive())
                    {           

                     gameLoopThread.setRunning(true);
                     gameLoopThread.start();

                    }
            }

也许logcat会有所帮助:

  

10-22 09:35:06.310:DEBUG / Buddies --------------------------->(10985):服务: OnReceive ACTION_HOME_RESUME被调用   10-22 09:35:06.315:DEBUG / AndroidRuntime(3275):关闭VM   10-22 09:35:06.315:WARN / dalvikvm(3275):threadid = 1:线程退出,未捕获异常(组= 0x4001e578)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):致命异常:主要   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):java.lang.NullPointerException   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):atmer.idunku3.GameView $ 1.surfaceDestroyed(GameView.java:126)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.view.SurfaceView.reportSurfaceDestroyed(SurfaceView.java:613)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.view.SurfaceView.updateWindow(SurfaceView.java:498)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.view.SurfaceView.updateWindow(SurfaceView.java:407)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:217)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.view.View.dispatchWindowVisibilityChanged(View.java:4080)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.view.ViewRoot.performTraversals(ViewRoot.java:790)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.view.ViewRoot.handleMessage(ViewRoot.java:1868)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.os.Handler.dispatchMessage(Handler.java:99)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.os.Looper.loop(Looper.java:123)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):在android.app.ActivityThread.main(ActivityThread.java:3691)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):at java.lang.reflect.Method.invokeNative(Native Method)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):at java.lang.reflect.Method.invoke(Method.java:507)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:847)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)   10-22 09:35:06.315:ERROR / AndroidRuntime(3275):at dalvik.system.NativeStart.main(Native Method)   10-22 09:35:06.320:ERROR /(18080):Dumpstate> /数据/日志/ dumpstate_app_error

2 个答案:

答案 0 :(得分:3)

我的应用程序随机(经常)在返回上一个活动时崩溃。 事实证明“try”语句没有按预期工作,因为在getHolder()方法之后Canvas c仍然可以为null。

while (running) {
    Canvas c=null;
    startTime=System.currentTimeMillis();
    try {
        c=view.getHolder().lockCanvas();
        if(c!=null){ // <- this is the line of code I had to add to make it work
            synchronized (view.getHolder()) {
                view.onDraw(c);
            }
        }
    } catch (Exception e) {}
    finally{
        if(c!=null)
        view.getHolder().unlockCanvasAndPost(c);
    }
    //...
}

答案 1 :(得分:2)

我不认为这部分是必要的:

synchronized (mPauseLock) {
        while (!running) {
            try {
                mPauseLock.wait();
            } catch (InterruptedException e) {
            }
        }
    }

如果你使用这个,你需要通知才能释放对wait()的锁定; 但尝试使用相同的代码,而不使用synchronized(mPauseLock)

编辑:

当您按下主页按钮时,您的问题的解决方案,应用程序崩溃,执行此操作:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    gameView = new GameView(this);
    setContentView(gameView); 
}

@Override
public void onPause(){
    super.onPause();
    gameView.gameLoopThread.setRunning(false);
    finish();
}

在GameView(SurfaceView)中创建构造函数:

public GameLoopThread gameLoopThread;

public GameView(Context context) {
    super(context);
    gameLoopThread = new GameLoopThread(this);
}