java - 退出 Activity 时 Android 4.0 上的线程崩溃

标签 java android thread-safety

在 Android 4.0 中使用标准游戏线程测试多个游戏时,它运行良好,直到 Activity 关闭(按下主页按钮等),使 Activity 应用程序崩溃并返回 nullPointer。

这甚至发生在 Google 编写的示例 LunarLander 中。

问题是离开 Activity 时 Canvas 变为 null,这会导致应用程序崩溃。

来自 LogCat 的错误消息就在下方。

02-27 18:07:58.974: V/MainThread(2667): CANVAS android.view.Surface$CompatibleCanvas@4102bcf0
02-27 18:07:59.164: V/MainThread(2667): CANVAS null
02-27 18:07:59.164: W/dalvikvm(2667): threadid=14: thread exiting with uncaught exception (group=0x409c01f8)
02-27 18:07:59.174: E/AndroidRuntime(2667): FATAL EXCEPTION: Thread-108
02-27 18:07:59.174: E/AndroidRuntime(2667): java.lang.NullPointerException
02-27 18:07:59.174: E/AndroidRuntime(2667):     at com.joakimengstrom.pong.MainThread.run(MainThread.java:49)

这是启动线程时的代码,带有您在上面看到的 Log.v。

    while(this.running){
        canvas = null;

        try {               
            canvas = this.surfaceHolder.lockCanvas(null);
            synchronized (surfaceHolder) {
                Log.v(TAG, "CANVAS " + canvas);
                canvas.drawColor(Color.BLACK);
                ...

下面是创建线程并在表面被销毁时将其关闭的情况。

@Override
public void surfaceCreated(SurfaceHolder holder) {
    thread = new MainThread(getHolder());
    thread.setRunning(true);
    thread.start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    boolean retry = true;
    thread.setRunning(false);
    while (retry) {
        try {
            thread.join();
            retry = false;
        } catch (InterruptedException e) {

        }
    }
}

如何在不使 Canvas 为空的情况下以安全的方式退出线程?

最佳答案

在 Android 4.0 中,SurfaceHolder.lockCanvas 可以在表面被销毁时返回 null。所以在这里:

try {               
            canvas = this.surfaceHolder.lockCanvas(null);
            synchronized (surfaceHolder) {
                Log.v(TAG, "CANVAS " + canvas);
                canvas.drawColor(Color.BLACK);

只需用 if (canvas != null) 包围您的 synchronized (surfaceHolder) block 。这不会导致应用程序的行为出现任何问题,因为它发生在不需要绘图时。

关于java - 退出 Activity 时 Android 4.0 上的线程崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9569698/

相关文章:

java - 如何为每个未点击的按钮添加积分?

c# - 这个非锁定的 TryGetValue() 字典访问线程安全吗?

ruby - 在 JRuby 中使用 ||= 和 +=(jruby-lint 警告)

java - 如何在JTree中只显示根?

java - 设置方法或构造函数

java - 为什么我无法膨胀包含 fragment 的布局?

java - 如何使用正则表达式从字符串中排除子字符串的出现?

android - 应用程序意外停止请重试?

android - 为什么不将 Intent 传递给 Android 中的上一个 Activity

python - 生成器是线程安全的吗?