Java Android ViewGroup 崩溃:尝试从空对象引用上的字段“int android.view.View.mViewFlags”读取
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33242776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android ViewGroup crash: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference
提问by M2014
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 代码记录的相关错误?
回答by kevinpelgrims
The problem is in the ViewGroup
's dispatchDraw()
method. This method tries to draw all the ViewGroup
's children. 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
).
问题出在ViewGroup
的dispatchDraw()
方法上。这种方法试图绘制所有ViewGroup
的孩子。当孩子是 时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.
所以问题是你的一个视图在某处没有正确初始化。恐怕这是我能做的最好的了。
回答by Hymansonkr
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. What I did was setup an asynchronousRunnable
to wait 100 milliseconds after the animation had stopped before removing the animated object:
我有同样的问题。我设置了一个,animation
然后onAnimationEnd
我正在删除已经动画的对象,这是问题开始的时候。我所做的是设置一个异步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
干杯
回答by Teemu L?tti
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. To be specific, I removed a view with children in my derived onDraw() when certain conditions were met. 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() 调用中添加代码来修改视图树时,它开始发生。具体来说,当满足某些条件时,我在派生的 onDraw() 中删除了一个带有孩子的视图。我现在认为这是一件坏事,可能是因为平台正在尝试绘制我现在从视图树中删除的视图。我通过在调用 onDraw() 完成后使用 Runnable 发布删除来解决该问题。
回答by veritas1
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.
我们也意外地开始收到此错误。它被追踪到片段动画是问题。更具体地说,replace()
当应用程序是针对Local Maven repository for Support Libraries
rev > 26构建时,在片段事务中使用自定义动画。
Possible solution
可能的解决方案
Downgrade Local Maven repository for Support Libraries
to rev 26. See here
降级Local Maven repository for Support Libraries
到 rev 26。见这里
回答by Pawan Chaurasiya
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
}
});
回答by Pierpaolo Pierpaoli
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;
}
}
回答by Pradeep
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. However, if you look deep into that, the hardware problem may come to be an issue. So just handle(catch) the issue.
尽管异常很常见,但导致原因的来源并不常见,并且在您拥有如此多的动态视图时会发生。有时在 Instagram 页面中滚动会导致此异常。但是,如果您深入研究,硬件问题可能会成为一个问题。所以只需处理(抓住)这个问题。
回答by Bassam Helal
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 :)
愿你平安:)