简体   繁体   English

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

[英]Android ViewGroup crash: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference

We have found several cases for this kind of crashes reported by backend logging monitoring.我们发现了几种由后端日志监控报告的此类崩溃的案例。 It seems the crashes do not tie to particular UX failure.崩溃似乎与特定的用户体验失败无关。 And from the reports, there is no sign of how our own classes being involved(no sign of any of our classes names).从报告来看,没有迹象表明我们自己的类是如何参与的(没有任何类名的迹象)。 Here is an example of typical crashes:以下是典型崩溃的示例:

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) 

Does anyone know whether there is related bug logged against Android code?有谁知道是否有针对 Android 代码记录的相关错误?

Possible Solution可能的解决方案

I had this same issue.我有同样的问题。 I setup an animation and in onAnimationEnd I was removing the object that had been animated which is when problems started.我设置了一个animation并在onAnimationEnd中删除了已经动画的对象,这是问题开始的时候。 What I did was setup an asynchronous Runnable to wait 100 milliseconds after the animation had stopped before removing the animated object:我所做的是设置一个异步Runnable在动画停止后等待 100 毫秒,然后再移除动画对象:

the object previously animated is this._loader之前动画的对象是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);
}

Cheers干杯

I was facing same problem.我面临同样的问题。 I resolved with Handler.我用Handler解决了。

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

The problem is in the ViewGroup 's dispatchDraw() method.问题出在ViewGroupdispatchDraw()方法中。 This method tries to draw all the ViewGroup 's children.此方法尝试绘制ViewGroup的所有子项。 When a child is null , you get an exception, which most likely comes from this line : if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { (notice the mViewFlags ).当孩子为null ,您会得到一个异常,这很可能来自这一行if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { (注意mViewFlags )。

So the problem is that one of your views, somewhere, is not properly initialized.所以问题是你的一个视图在某处没有正确初始化。 I'm afraid that's the best I can do.恐怕这是我能做的最好的了。

We started getting this error unexpectedly too.我们也意外地开始收到此错误。 It was tracked down to fragment animations being the issue.它被追踪到片段动画是问题。 More specifically using custom animations with replace() in a fragment transaction when the app is built against Local Maven repository for Support Libraries rev > 26.更具体地说,当Local Maven repository for Support Libraries rev > 26 的Local Maven repository for Support Libraries构建应用程序时,在片段事务中使用带有replace()自定义动画。

Possible solution可能的解决方案

Downgrade Local Maven repository for Support Libraries to rev 26. See here Local Maven repository for Support Libraries降级到修订版 26。请参见此处

Possible cause: I was having the exact same issue.可能的原因:我遇到了完全相同的问题。 It turned out it started to happen when I added code to modify the view tree within onDraw() call.事实证明,当我在 onDraw() 调用中添加代码来修改视图树时,它开始发生。 To be specific, I removed a view with children in my derived onDraw() when certain conditions were met.具体来说,当满足某些条件时,我在派生的 onDraw() 中删除了一个带有孩子的视图。 I now believe this is a bad thing to do, probably because the platform is trying to draw views that I have now removed from the view tree.我现在认为这是一件坏事,可能是因为平台正在尝试绘制我现在从视图树中删除的视图。 I resolved the issue by posting the deletion with Runnable to happen after the call to onDraw() has finished.我通过在调用 onDraw() 完成后使用 Runnable 发布删除来解决该问题。

Override dispatchDraw method and put in it a try/catch block, like this:覆盖 dispatchDraw 方法并在其中放入一个 try/catch 块,如下所示:

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

        }
        catch(Exception exception)
        {
            return;
        }
    }

Even though the exception is common, the causing source is uncommon and occurs when you have so many dynamic views .尽管异常很常见,但导致原因的来源并不常见,并且在您拥有如此多的动态视图时会发生 Sometimes scrolling in the Instagram page cause this exception.有时在 Instagram 页面中滚动会导致此异常。 However, if you look deep into that, the hardware problem may come to be an issue .但是,如果您深入研究,硬件问题可能会成为一个问题 So just handle( catch ) the issue.所以只需处理(抓住)这个问题。

While it is ugly and not good practice, the only thing I could get to reliably work is just catching the exception in dispatchDraw() like below:虽然这很丑陋而且不是很好的做法,但我唯一能可靠地工作的就是在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) {

        }
    }

Just make sure your desired behavior is working correctly and you're not breaking something else by doing this.只需确保您想要的行为正常工作,并且这样做不会破坏其他东西。 Again, not ideal, but it's the only thing I could get to work and I'm absolutely sure in my case it's not breaking anything else.同样,这并不理想,但这是我唯一可以开始工作的东西,而且我绝对确定在我的情况下它不会破坏其他任何东西。

Peace to you :)愿你平安:)

I was trying to navigate from Fragment A to Fragment B , and Fragment A was a form that required data from Fragment B .我试图从Fragment A导航到Fragment B ,而Fragment A是一种需要来自Fragment B 的数据的表单。

So when I tried to navigate without filling up A , it was throwing this exception.所以当我试图在不填写A 的情况下导航时,它抛出了这个异常。

Also, even if A was independent of the data B , it was throwing this exception.此外,即使A独立于数据B ,它也会抛出此异常。

I have no idea why but I added a condition where the user had to fill-up the form before navigating away and that solved the issue.我不知道为什么,但我添加了一个条件,即用户必须在导航之前填写表单并解决了问题。

It's a threading issue.这是线程问题。 Could be that you're refreshing your ViewPager or some other adapter.可能是您正在刷新ViewPager或其他一些适配器。

Have been facing this issue on and off, and realised that if you place it in the UI Thread in your Activity , then it'll render just fine.一直在面对这个问题,并意识到如果你把它放在你的Activity的 UI 线程中,那么它会呈现得很好。

activity?.runOnUiThread{
   // Add Your UI Updating Methods Here
}

No delay / threading stuff required.不需要延迟/线程处理。 Plz Read through... The post is old but for the future readers, it would be helpful.请通读...这篇文章很旧,但对于未来的读者来说,它会有所帮助。 I explain in details what really happens with a use-case I faced and solved.我详细解释了我遇到并解决的用例的实际情况。

I have a viewflipper which animates flipping next and previous through its children using simple slide-in / slide-out animations.我有一个 viewflipper,它使用简单的滑入/滑出动画通过其子项动画翻转下一个和上一个。 I need to remove a view from viewflipper just after flipping is completed and to make sure it happens at the right time, slide-in animations have a listener where I remove the view in there.我需要在翻转完成后立即从 viewflipper 中删除一个视图,并确保它在正确的时间发生,滑入动画有一个监听器,我可以在那里删除视图。 Everything worked perfect for flip-to-next while flip-to-previous threw the above mentioned exception.一切都非常适合翻转到下一个,而翻转到上一个则抛出上述异常。 After some trial and error turns out:经过一些试验和错误结果:

when flipping to next the following is the sequence:翻到 next 时,顺序如下:

1-slide-out starts
2-slide-in starts
3-slide-out finishes
4-slide-in finishes

So having listener on slide-in is the right thing since both animations are guaranteed to be completed there.因此,在滑入式中使用侦听器是正确的,因为两个动画都保证在那里完成。

But when flipping to previous the following is the sequence:但是当翻到前一个时,顺序如下:

1-slide-in starts
2-slide-out starts
3-slide-in finishes
4-slide-out finishes

As you can see, when slide-in finishes, slide-out is not done yet and hence there happens the exception.如您所见,当滑入完成时,滑出尚未完成,因此发生了异常。 I simply set the listener on slide-out and it worked perfectly.我只是将侦听器设置为滑出式,并且效果很好。

While all of the other answers urge to remove the view with a delay (which of course helps to make sure concurrent animations are all done) but as you could see that is not the case.虽然所有其他答案都敦促延迟删除视图(这当然有助于确保并发动画全部完成),但正如您所见,情况并非如此。

As a general rule, when you have a set of animations running on a view (even with the exact same durations) -although the general belief is that they would finish both together - but they won't (remember that threads are virtually concurrent).作为一般规则,当您在视图上运行一组动画时(即使具有完全相同的持续时间) - 尽管普遍认为它们会同时完成 - 但它们不会(请记住线程实际上是并发的) .

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.lang.NullPointerException:尝试在空对象引用上调用虚方法'int android.view.ViewGroup.getPaddingLeft()' - java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.ViewGroup.getPaddingLeft()' on a null object reference 尝试从 null object 参考上的字段 'android.view.View androidx.recyclerview.widget.RecyclerView$b0.a' 中读取 - Attempt to read from field 'android.view.View androidx.recyclerview.widget.RecyclerView$b0.a' on a null object reference 尝试在空对象引用上调用虚拟方法 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()' - Attempt to invoke virtual method 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()' on a null object reference 尝试从字段 'android.view.View androidx.recyclerview.widget.RecyclerView$ViewHolder.itemView' 读取 null object 参考 - Attempt to read from field 'android.view.View androidx.recyclerview.widget.RecyclerView$ViewHolder.itemView' on a null object reference NullPointerException:尝试从空对象引用上的字段'int android.app.Fragment.mContainerId'读取 - NullPointerException: Attempt to read from field 'int android.app.Fragment.mContainerId' on a null object reference Android Listview: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference - Android Listview: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference 尝试在 null object 参考上调用虚拟方法 'void android.view.View.measure(int, int)' - Attempt to invoke virtual method 'void android.view.View.measure(int, int)' on a null object reference FacebookSdk尝试在空对象引用上调用虚拟方法'android.view.View android.view.View.findViewById(int)' - FacebookSdk Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference 尝试在空对象引用上调用虚方法'int android.view.View.getImportantForAccessibility()' - Attempt to invoke virtual method 'int android.view.View.getImportantForAccessibility()' on a null object reference 尝试在空对象引用上调用虚拟方法'android.view.View android.view.View.findViewById(int)' - Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM