【问题标题】:NullPointerException in SurfaceView.onAttachedToWindow(SurfaceView.java:207)SurfaceView.onAttachedToWindow 中的 NullPointerException(SurfaceView.java:207)
【发布时间】:2014-03-13 20:31:20
【问题描述】:

我从 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)

-- 编辑--

抱歉,我忘了提,我不知道重现异常的步骤。每次我运行该应用程序时,该代码都有效,但我从三星 Galaxy Tab 3 将这些异常发送到我的记录器。而且问题并不一致。

【问题讨论】:

  • 你使用哪个android API? 19 ?
  • 我使用的是 API 级别 15。
  • 你好,凯尔,你有没有解决这个问题?我找到了一种重现它的方法:获取一个带有相机预览和相机启动按钮和相机停止按钮的应用程序。现在,如果你遇到一个疯狂的用户,并且他在不到 2 秒的时间内按下 : Start Stop Start,就会抛出这个异常。
  • @rupinderjeet 很有趣。我没有考虑到这一点。自从我重写了我的相机实现后,我实际上已经忘记了这个问题。我最终编写了一个状态机,以确保在相机未准备好时不会调用任何东西。

标签: android


【解决方案1】:

我相信您的错误是因为您在此行中使用了陈旧的视图:

setPreviewDisplay(this.surfaceView.getHolder())

在这一行中,当它崩溃时,surfaceView 不再有效。您应该使用在 surfaceChanged/surfaceCreated 中返回的 SurfaceHolder。

这也是我的错误的来源。

一般:

当您尝试将视图(您的预览)附加到不再存在的窗口时,可能会发生此错误。例如,您有一些长时间运行的代码(打开相机),然后附加视图,并且手机已旋转(旧上下文)或正在显示另一个应用程序(因此附加到看不见的视图无效),或者锁屏开启等。

避免这种情况的一种方法是在尝试附加视图之前确保有一个可见的 Activity 窗口。我希望我有更多的细节来告诉你如何做到这一点。

一个可能的问题是您正在执行 Camera.open(),这可能需要一些时间,尤其是在某些设备上,在您调用 addView() 之前,所以可能在您开始使用 addView() 时,窗口不可用。考虑在后台线程上执行 Camera.open(),当所有这些都完成后,执行 addView()。

我看到您在 UI 线程上运行了多个线程。在执行 addView 之前,您要确保所有这些都已完成。

【讨论】:

  • 这似乎很可能是问题所在。适应这种竞争条件的最佳方法是什么?
  • @Kyle 我想我找到了你崩溃的根源——让我知道!请参阅我的更新答案。
  • @Lucy,还有什么比这更可疑的吗?我认为在camera.open() 之后立即执行setPreviewDisplay() 也会导致这种情况。您是否碰巧找到了更多信息?
  • @rupinderjeet 我没有任何其他信息。就像我说的,考虑在后台线程上执行 Camera.open(),当所有这些都完成后,做你的事。
【解决方案2】:

我不知道是什么原因造成的,但我只能想到一种解决方法:

    this.surfaceView = new SurfaceView(customContext) {
        /* (non-Javadoc)
         * @see android.view.SurfaceView#onAttachedToWindow()
         */
        @Override
        protected void onAttachedToWindow() {
            if(this.getParent() != null)
                super.onAttachedToWindow();
        }
    };

虽然无法测试它是否会产生更多问题或只是修复这个问题。

我知道这很骇人听闻,但我认为编写它不会有什么坏处。

风险自负!

【讨论】:

  • this.getParent() 什么都不是。
  • 什么意思?
  • this 没有 getParent() 方法。在这种情况下,您的thisSurfaceView。而且,Mr.SurfaceView 不提供任何getParent() 方法。
  • 老实说,我不记得这是从 2014 年开始的,也许我的意思是CurrentClass.this.getParent(),但我现在不能确定,因为我换了工作,我不再做安卓了
【解决方案3】:

CameraPluginView 类的构造函数中,你通过 customContext

           this.surfaceView = new SurfaceView(getContext());

试试这个constructor

         SurfaceView(Context context, AttributeSet attrs)

“在从 XML 扩展视图时调用”

【讨论】:

  • 对不起,这是我的错字。我试图删除项目可识别的任何内容,却忘记将这些引用从“上下文”更新为“customContext”。我已经在代码中进行了更新。请放心,实际代码和您看到的代码之间唯一改变的只是对象的名称。
  • 我认为您还必须提供SurfaceView 类文件,因为onAttachedToWindow 内部发生异常。在我看来,这会有所帮助。
  • SurfaceView 是 Android SDK 的一部分 :)
  • 我现在稍微改变了答案,最好通过这个,这意味着CameraPluginView 本身。
  • CameraPluginView 是 View 的间接子类。没有它在哪里继承上下文。因此,将 SurfaceView 的上下文设置为“this”会给我一个不兼容错误。
【解决方案4】:

您的 mParent 可能为 null,因为可能未调用 View.java 中的 assignView。检查这个。检查问题的简单方法 - 使用TextView 创建示例项目并逐步检查调试(在assignView() 方法和onAttachedToWindow() 中设置断点),您将看到问题所在。

【讨论】:

  • 问题是它不容易重现。
猜你喜欢
  • 1970-01-01
  • 2015-10-29
  • 2015-04-27
  • 1970-01-01
  • 1970-01-01
  • 2019-11-10
  • 2014-04-12
  • 2014-01-02
  • 2021-08-05
相关资源
最近更新 更多