我们在应用程序的不同部分看到了此 ANR。 想了解导致此 ANR 的原因吗?
main (native): tid=1 systid=31940
#00 pc 0x5431c libc.so
#01 pc 0x1313a5 libart.so
#02 pc 0x2ab05b libart.so
#03 pc 0x3659 libnativehelper.so
#04 pc 0x9dee9 libandroid_runtime.so
#05 pc 0x65c45 libgui.so
#06 pc 0x11dcd libutils.so
#07 pc 0x11abf libutils.so
#08 pc 0xbcc7d libandroid_runtime.so
at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
at android.os.MessageQueue.next(MessageQueue.java:339)
at android.os.Looper.loop(Looper.java:199)
at android.app.ActivityThread.main(ActivityThread.java:8276)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)
这就是 firebase 对于此 ANR 的说法 -
发生ANR时该线程处于空闲状态。我们没有足够的 确定根本原因的信息。
NativePollOnce:
当CPU等待新任务/消息时出现。
原因:
收集ANR的方式:
解决ANR的挑战:
揭开 ANR 之谜。 链接
解决方案:
面临同样的问题 - 我读到它与 Admob 或 unity 广告有关,并且谷歌有一个开放线程:https://issuetracker.google.com/issues/230950647?pli=1
在最新版本的 Cloud Messaging 依赖项 v23.0.7 Firebase 中提到此版本可能会减少 ANR。这是他在其文档中提到的话。
消息广播现在在绑定到服务后立即完成。此更改应该会减少出现 ANR 的机会
就我而言,这是 firebase 云消息传递库中的错误。该错误已在2022年12月8日发布的最新版本23.1.1中修复。
https://firebase.google.com/support/release-notes/android#messaging_v23-1-1
希望对您有帮助。
可能的原因:UI 线程被同步屏障阻塞。
如果 UI 线程的
MessageQueue
有同步屏障,所有消息都将被阻塞(异步消息除外),直到同步屏障被移除。
什么会导致这个问题?
如果您在非 UI 线程中使视图无效,则可能会遇到此问题。
为什么?
// View.java
public void invalidate() {
invalidate(true);
}
public void invalidate(boolean invalidateCache) {
invalidateInternal(...);
}
void invalidateInternal(...) {
final ViewParent p = mParent;
p.invalidateChild(this, damage);
}
// ViewGroup.java
public final void invalidateChild(View child, final Rect dirty) {
onDescendantInvalidated(child, child);
}
public void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
//...
if (mParent != null) {
mParent.onDescendantInvalidated(this, target);
}
}
ViewRootImpl
是最上面的ViewParent
:
public void onDescendantInvalidated(@NonNull View child, @NonNull View descendant) {
// TODO: Re-enable after camera is fixed or consider targetSdk checking this
// checkThread();
invalidate();
}
void invalidate() {
scheduleTraversals();
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
}
}
void unscheduleTraversals() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
}
注意上面代码片段中的
和postSyncBarrier
removeSyncBarrier
这里在
onDescendantInvalidated
的ViewRootImpl
中,它没有检查它是否在UI线程中。
因此,如果您偶尔在非 ui 线程中
invalidate
查看视图,则可能会在消息队列中留下同步屏障,而稍后不会被删除,然后您就会遇到此问题。
我是否
invalidate
我的视图脱离了ui线程?
就我而言,我向许多视图提供
BitmapDrawable
,然后我可能会在工作线程中更改 bitmap
的 BitmapDrawable
。这将导致使用 BitmapDrawable
的视图在工作线程中失效。
如何检查非ui线程中是否有视图失效?
在视图层次结构的最顶层
ViewGroup
中,覆盖 onDescendantInvalidated
:
override fun onDescendantInvalidated(child: View, target: View) {
super.onDescendantInvalidated(child, target)
if (Looper.getMainLooper() != Looper.myLooper()) {
throw RuntimeException("no ui thread")
}
}
问题的典型症状
RecyclerView
或ListView
可以正常滚动,但任何视图的点击监听器都不起作用。MessageQueue.nativePollOnce
BroadcastTimeout
anr 或 ServiceTimeout
anr,但不是 KeyDispatchTimeout
anr