Android ViewGroup崩溃:尝试从null对象引用上的字段'int android.view.View.mViewFlags'中读取


69

我们发现后端日志记录监视报告了此类崩溃的几种情况。崩溃似乎与特定的UX故障无关。从报告中,没有迹象表明我们自己的班级是如何参与的(没有任何班级名称的迹象)。这是典型崩溃的示例:

java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference 
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3357) 
at android.view.View.updateDisplayListIfDirty(View.java:14288) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3549) 
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3528) 
at android.view.View.updateDisplayListIfDirty(View.java:14253) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3549) 
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3528) 
at android.view.View.updateDisplayListIfDirty(View.java:14253) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3549) 
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3528) 
at android.view.View.updateDisplayListIfDirty(View.java:14253) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3549) 
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3528) 
at android.view.View.updateDisplayListIfDirty(View.java:14253) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3549) 
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3528) 
at android.view.View.updateDisplayListIfDirty(View.java:14253) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3549) 
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3528) 
at android.view.View.updateDisplayListIfDirty(View.java:14253) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3549) 
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3528) 
at android.view.View.updateDisplayListIfDirty(View.java:14253) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3549) 
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3528) 
at android.view.View.updateDisplayListIfDirty(View.java:14253) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3549) 
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3528) 
at android.view.View.updateDisplayListIfDirty(View.java:14253) 
at android.view.View.getDisplayList(View.java:14315) 
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:273) 
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:279) 
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:318) 
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2561) 
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2377) 
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2007) 
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1086) 
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6453) 
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:846) 
at android.view.Choreographer.doCallbacks(Choreographer.java:647) 
at android.view.Choreographer.doFrame(Choreographer.java:601) 
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:829) 
at android.os.Handler.handleCallback(Handler.java:739) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:135) 
at android.app.ActivityThread.main(ActivityThread.java:5254) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:927) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:713) 

有谁知道针对Android代码是否记录了相关的错误?


我看到了完全相同的崩溃,但是我没有看到其他地方引用过它。到目前为止,至少在我看来,这似乎只发生在棉花糖设备上。
sa.shadow

我正面临着同样的问题。与@ sa.shadow相反,我在棉花糖之前的设备上也遇到了它,特别是在棒棒糖上。我注意到的另一件事是,它似乎仅在我的列表(RecyclerView)为空时才发生。
MathieuMaree'1

2
我想补充一点,我在使用SwipeRefreshLayout和空的RecyclerView进行刷新以刷新时一直在体验
MathieuMaree,2016年

我敢打赌这是一个Android错误:)您可以在git上共享代码进行调试吗?
ceph3us

1
请提供可用于重现此崩溃的代码
gio

Answers:


29

可能的解决方案

我有同样的问题。我设置了一个,animation然后在onAnimationEnd删除问题时开始动画的对象。我所做的是设置了一个异步, Runnable以便在动画停止后等待100毫秒,然后再删除动画对象:

先前动画的对象是 this._loader

private void removeLoader() {
    final ContentContainer self = this; // "CustomContainer" needs to match the type of `this`
    Handler h = new Handler();
    h.postAtTime(new Runnable() {
        @Override
        public void run() {
            MainActivity.instance.runOnUiThread(new Runnable() { 
                @Override
                public void run() {
                    try {
                        if(self._loader == null) {
                            // there is no loader. quit now while you still have the chance!!
                            return;
                        }
                        while(self._loader.getParent() != null) {
                            removeView(self._loader);
                        }
                    } catch(Exception e) {
                        Crashlytics.logException(e);
                        e.printStackTrace();
                    }

                    self._loader = null;
                }
            });
        }
    }, 100);
}

干杯


3
讨厌,讨厌不得不做这样的事情,无论如何都要为头脑欢呼
Dean Wild

@DeanWild我完全同意。我敢肯定,这样做有一种安全可靠的方法,但我敢说,“适当的”解决方案所需的时间和创造力超过了快速破解的好处,但我以前错了……
杰克逊(Jacksonkr)

2
@Jacksonkr感谢您的回答。在我的情况简单地把removeView在呼叫runnablepost在同一个视图中的编removeView叫上固定的问题。这感觉像是“更合适的”解决方案,因为没有延迟。
Daniel F

您正在跳过runOnUiThread吗?根据可能使人陷入热水的设置而定。
杰克逊(Jacksonkr)

1
通过使用postAtTime()您无意间执行的操作,永远不会调用可运行对象。我确定您的意思是postDelayed()相反,但是事实可以解决您的问题,这使我相信这根本不是解决方案。您实际上是将视图保留在内存中。对于用例,例如在RecyclerView中设置视图动画,这确实不是解决方案。
Paul Lammertsma '18 -10-22

16

我面临着同样的问题。我与Handler解决了。

new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                   // remove fragment from here
                }
            });

从错误消息来看不是很明显,但是就我而言,它是在AnimationListener中删除视图。将其发布以返回主线程即可解决该问题。
戴维·贝里

12

问题出在ViewGroupdispatchDraw()方法中。此方法尝试绘制所有ViewGroup的孩子。当孩子是时null,您会得到一个例外,该例外很可能来自此行:(请if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {注意mViewFlags)。

因此,问题在于您的某个视图在某处未正确初始化。恐怕这是我能做的最好的。


4

我们也开始意外收到此错误。它被追踪到片段动画成为问题。更具体地说,replace()当针对Local Maven repository for Support Librariesrev> 26构建应用程序时,在片段事务中使用自定义动画。

可能的解决方案

降级Local Maven repository for Support Libraries到26版。请参见此处


2

可能的原因: 我遇到了完全相同的问题。事实证明,当我添加代码以在onDraw()调用中修改视图树时,它开始发生。具体来说,当满足某些条件时,我在派生的onDraw()中删除了带有子视图的视图。我现在认为这是一件坏事,这可能是因为平台试图绘制我现在从视图树中删除的视图。我通过在对onDraw()的调用完成之后发布带有Runnable的删除来解决了该问题。


1

覆盖dispatchDraw方法,并在其中放入一个try / catch块,如下所示:

public void dispatchDraw(Canvas c)
    {
        try
        {
            super.dispatchDraw(c);
            return;

        }
        catch(Exception exception)
        {
            return;
        }
    }

0

即使异常是很常见的,但引起原因的来源并不常见,并且在您拥有如此多的动态视图时会发生。有时在Instagram页面中滚动会导致此异常。但是,如果您对此进行深入研究,则可能是硬件问题。因此,只需处理(抓住)问题。


0

虽然这很丑陋,也不是很好的做法,但是我要可靠地工作的唯一方法就是捕获异常,dispatchDraw()如下所示:

override fun dispatchDraw(canvas: Canvas?) {
        /*
         * We're doing this because of the below exception that is out of our control:
         * java.lang.NullPointerException: Attempt to read from field
         * 'int android.view.View.mViewFlags' on a null object reference at
         * android.view.ViewGroup.dispatchDraw(ViewGroup.java:4111)
         */
        try {
            super.dispatchDraw(canvas)
        } catch (e: NullPointerException) {

        }
    }

只需确保您期望的行为正常运行,并且这样做就不会破坏其他功能。同样,这不是理想的选择,但这是我唯一可以做的事情,而且我绝对确定这不会破坏其他任何东西。

和平给你:)


0

我试图从Fragment A导航到Fragment B,而Fragment A是需要来自Fragment B的数据的形式

因此,当我尝试导航但未填满A时,它抛出了此异常。

同样,即使A独立于数据B,它引发此异常。

我不知道为什么,但是我添加了一个条件,即用户在导航之前必须填写表格,这解决了问题。


0

这是一个线程问题。可能是您正在刷新ViewPager适配器或其他适配器。

已经不停地面对这个问题,并意识到,如果将其放置在中的UI线程中Activity,它将很好地呈现。

activity?.runOnUiThread{
   // Add Your UI Updating Methods Here
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.