Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android API级别15上的SurfaceView线程中出现意外的NullPointerException_Android_Multithreading_Surfaceview - Fatal编程技术网

Android API级别15上的SurfaceView线程中出现意外的NullPointerException

Android API级别15上的SurfaceView线程中出现意外的NullPointerException,android,multithreading,surfaceview,Android,Multithreading,Surfaceview,我已经编写了一个应用程序,我想在更高的API级别上进行测试,以检查兼容性。对于API 10(2.3.3),没有问题,但当我在API 15(4.0.3)上运行我的应用程序时,当我退出活动时,我的一个SurfaceView中出现了NullPointerException。 我不得不说我解决了这个问题,但我不明白为什么会发生异常。也许你可以告诉我 以下是在API 10上为我工作的代码: 这是run()-方法的常见结构 public void run() { while (mThreadActi

我已经编写了一个应用程序,我想在更高的API级别上进行测试,以检查兼容性。对于API 10(2.3.3),没有问题,但当我在API 15(4.0.3)上运行我的应用程序时,当我退出活动时,我的一个SurfaceView中出现了NullPointerException。 我不得不说我解决了这个问题,但我不明白为什么会发生异常。也许你可以告诉我

以下是在API 10上为我工作的代码: 这是
run()
-方法的常见结构

public void run() {
    while (mThreadActive) {
        c = null;
        try {
            c = mSurfaceHolder.lockCanvas(null);
            synchronized (mSurfaceHolder) {
                if(mState == 1) {
                    updateValues();
                    updateAnimation();
                }
                doDraw(c);
            }
        } finally {
            if (c != null) {
                mSurfaceHolder.unlockCanvasAndPost(c);
            }
        }
    }
}
在API 15上退出活动时: 当
doDraw()
-方法试图在“c”上写入时出现异常。我检查了c,发现它是空的,所以毫不奇怪我得到了一个异常。我还检查了
mThreadActive
,发现尽管我将其设置为false,但
while
-循环仍然会触发。 以下是代码示例:

public void run() {
    while (mThreadActive) {
        c = null;
        try {
            c = mSurfaceHolder.lockCanvas(null);
            synchronized (mSurfaceHolder) {
                if(mState == 1) {
                    updateValues();
                    updateAnimation();
                }

                if(!mThreadActive)    // so it really is!
                    Log.d("Thread", "mThreadActive is false!");

                if(c == null)   // so it is too!
                    Log.d("Thread", "c is null!");

                doDraw(c);   // error
            }
        } finally {
            if (c != null) {
                mSurfaceHolder.unlockCanvasAndPost(c);
            }
        }
    }
}
我可以想象为什么
mThreadActive
在被
while
-语句检查后变为false,但我无法理解为什么在
mSurfaceHolder.lockCanvas(null)
之后“c”为null。代码似乎不是按顺序运行的

好的,解决方法是检查
c!=在其上绘图之前为空:

public void run() {
    while (mThreadActive) {
        c = null;
        try {
            c = mSurfaceHolder.lockCanvas(null);
            synchronized (mSurfaceHolder) {
                if(mState == 1) {
                    updateValues();
                    updateAnimation();
                }
                if(c != null) // prevent drawing on c if c doesnt exist.
                    doDraw(c);
            }
        } finally {
            if (c != null) {
                mSurfaceHolder.unlockCanvasAndPost(c);
            }
        }
    }
}
那么,为什么在API 15上会出现异常,而在API 10上却可以正常工作呢? 另一件有趣的事是,我有其他具有相同结构的SurfaceView,但与此相比,它们都工作得很好! 为什么代码不是按顺序运行的?是不是因为我在一个模拟器上进行测试(这是相当滞后的)


谢谢。

您提到,尽管
mThreadActive
为false,您的
while()
循环似乎仍在继续。
mThreadActive
是否标记为
volatile
?可能需要这样做

另外,
lockCanvas(null)
。因为我们看不到您的代码的其余部分,所以不清楚您想做什么。API对将
null
传入
lockCanvas
有何说明?(我们谈论的是
SurfaceHolder
的原始实例还是子类?)

请注意,的API规范指示它可以返回
null

如果尚未创建曲面或无法编辑曲面,则返回null。通常需要实现Callback.surfaceCreated,以确定曲面何时可用


通过阅读API,您似乎应该实现接口并响应事件,这实际上是告诉您准备好写入画布的事件。

调用时,我也遇到了一个非常类似的问题:

public void surfaceDestroyed(SurfaceHolder holder)  {
    isAttached = false;
    this.drawthread = null;
}
退出应用程序以停止绘图线程时-我使用的while布尔值
isAttached
为false,但该while循环中的绘图代码仍在执行-退出时出现nullexception。不是一个表演的停止者,而是一些我真的想要修复的东西。我也在考虑一种
if(canvas!=null)
的解决方案,但我认为一定有更好的方法

现在,这个错误有一个奇怪的地方——它只在某些时候发生——在速度更快的设备上发生得更少。我所看到的问题是,
holder.lockCanvas()
返回null,这意味着在布尔值设置为false之前,holder将被销毁,而while有机会停止执行线程。线程竞争问题

找到了一个可能的解决方案,该解决方案在使while布尔值为null之前使用了
Thread.join()
,但是
holder.lockCanvas()
返回null时,holder在绘图完成之前被销毁,因此它有点毫无意义,仍然会导致null异常

我能想到的唯一其他解决方案是重写back按钮方法,并在销毁surfaceview(如果是poss)之前强制while bool为null,但我认为
if(canvas!=null)
可能更干净。还有什么其他的想法渴望听到吗


编辑:没有在其他地方测试过,但是我使用API 17得到错误,你能发布实际的异常跟踪吗?相关?
lockCanvas()
中的
null
对我的代码没有任何意义。我现在把它掉了。它应该是
lockCanvas(Rect dirty)
。我已经实现了
SurfaceHolder.Callback
接口。在
surfaceCreated()。紧接着,我激活(mThreadActive=true)并启动线程(
run()
)。我还将
mThreadActive
标记为volatile。似乎
while()
不再继续,但不知何故c仍然被调用并抛出其异常。也许它是从以前的while迭代调用的?