我从SurfaceView.onAttachedToWindow得到这个异常。它看起来像SurfaceView试图引用mParent,但它是空的。有人知道为什么父不会被设置,但onAttachedToWindow将被调用?
我正在使用SurfaceView进行相机预览。我有一个ViewGroup,从活动的根视图添加/删除。在ViewGroup内部是一个SurfaceView和一个WebView。
下面是ViewGroup的代码:http://pastebin.com/eSyZ3v3P,下面是显示/隐藏相机的代码:http://pastebin.com/5iaEFCQr
任何帮助都将非常感激。
下面是完整的堆栈跟踪:java.lang.NullPointerException
at android.view.SurfaceView.onAttachedToWindow(SurfaceView.java:207)
at android.view.View.dispatchAttachedToWindow(View.java:11755)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1199)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4212)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
at android.view.Choreographer.doCallbacks(Choreographer.java:555)
at android.view.Choreographer.doFrame(Choreographer.java:525)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
—edit—
对不起,我忘了说,我不知道重现异常的步骤。每次我运行应用程序的代码工作,但我得到这些异常从三星Galaxy Tab 3发送到我的记录器。这个问题并不是始终如一的。
我相信你的错误是因为你在这一行使用了一个过时的视图:
setPreviewDisplay(this.surfaceView.getHolder())
在这一行中,当它崩溃时,surfaceView不再有效。你应该使用surfaceChanged/surfaceCreated返回的SurfaceHolder。
这也是我的bug的来源。
一般:
当您试图将视图(预览)附加到不再存在的窗口时,可能会发生此错误。例如,你有一些长时间运行的代码(打开相机),然后你附加视图,手机已经旋转(旧的上下文)或另一个应用程序正在显示(所以它是无效的附加到看不见的视图),或者锁屏是打开的,等等。
避免这种情况的一种方法是确保在您尝试附加视图之前您的Activity有一个可见窗口。我希望我有更多的细节告诉你怎么做。
一个可能的问题是你正在做Camera.open(),这可能需要一些时间,特别是在某些设备上,在你调用addView()之前,所以也许当你绕过addView()时,窗口不可用。考虑在后台线程上执行Camera.open(),当所有这些都完成后,执行addView()。
我看到你有几个线程在UI线程上运行。你要确保这些在addView之前都完成了。
我不知道是什么原因,但我能想到的只有一个工作:
this.surfaceView = new SurfaceView(customContext) {
/* (non-Javadoc)
* @see android.view.SurfaceView#onAttachedToWindow()
*/
@Override
protected void onAttachedToWindow() {
if(this.getParent() != null)
super.onAttachedToWindow();
}
};
不能测试它,看看它是否会产生更多的问题,或者只是修复这个。
我知道这很粗俗,但我想写下来也无妨。
试试吧,风险自负!
在CameraPluginView类的构造函数中,传递customContext
this.surfaceView = new SurfaceView(getContext());
代替前面的调用,试试这个构造函数:
SurfaceView(Context context, AttributeSet attrs)
您的mParent可能为空,因为View.java中的assignView可能未被调用。检查这个。检查错误的简单方法-使用TextView
创建一个示例项目并逐步检查调试(在assignView()
方法和onAttachedToWindow()
中设置断点),您将看到问题所在。