排查无障碍相关的IndexOutOfBoundsException神秘崩溃问题
排查Material Design导航菜单无障碍相关崩溃(Activity退出后触发)
我正在排查应用分析工具上报的崩溃,堆栈信息如下:
java.lang.IndexOutOfBoundsException: Index: 8, Size: 8 at java.util.ArrayList.get(ArrayList.java:437) at com.google.android.material.internal.NavigationMenuPresenter$NavigationMenuAdapter.getItemViewType(NavigationMenuPresenter.java:553) at com.google.android.material.internal.NavigationMenuPresenter$NavigationMenuAdapter.adjustItemPositionForA11yDelegate(NavigationMenuPresenter.java:673) at com.google.android.material.internal.NavigationMenuPresenter$NavigationMenuAdapter.access$100(NavigationMenuPresenter.java:523) at com.google.android.material.internal.NavigationMenuPresenter$NavigationMenuAdapter$1.onInitializeAccessibilityNodeInfo(NavigationMenuPresenter.java:659) at androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate$ItemDelegate.onInitializeAccessibilityNodeInfo(RecyclerViewAccessibilityDelegate.java:163) at androidx.core.view.AccessibilityDelegateCompat$AccessibilityDelegateAdapter.onInitializeAccessibilityNodeInfo(AccessibilityDelegateCompat.java:89) at android.view.View.onInitializeAccessibilityNodeInfo(View.java:8609) at androidx.appcompat.widget.LinearLayoutCompat.onInitializeAccessibilityNodeInfo(LinearLayoutCompat.java:1794) at android.view.View.createAccessibilityNodeInfoInternal(View.java:8570) at android.view.View$AccessibilityDelegate.createAccessibilityNodeInfo(View.java:29784) at android.view.View.createAccessibilityNodeInfo(View.java:8553) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1271) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchAccessibilityNodeInfos(AccessibilityInteractionController.java:1096) at android.view.AccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdUiThread(AccessibilityInteractionController.java:342) at android.view.AccessibilityInteractionController.access$400(AccessibilityInteractionController.java:75) at android.view.AccessibilityInteractionController$PrivateHandler.handleMessage(AccessibilityInteractionController.java:1460) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7680) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:423) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) java.lang.IndexOutOfBoundsException: Index: 8, Size: 8 at java.util.ArrayList.get(ArrayList.java:437) at com.google.android.material.internal.NavigationMenuPresenter$NavigationMenuAdapter.getItemViewType(NavigationMenuPresenter.java:553) at com.google.android.material.internal.NavigationMenuPresenter$NavigationMenuAdapter.adjustItemPositionForA11yDelegate(NavigationMenuPresenter.java:673) at com.google.android.material.internal.NavigationMenuPresenter$NavigationMenuAdapter.access$100(NavigationMenuPresenter.java:523) at com.google.android.material.internal.NavigationMenuPresenter$NavigationMenuAdapter$1.onInitializeAccessibilityNodeInfo(NavigationMenuPresenter.java:659) at androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate$ItemDelegate.onInitializeAccessibilityNodeInfo(RecyclerViewAccessibilityDelegate.java:163) at androidx.core.view.AccessibilityDelegateCompat$AccessibilityDelegateAdapter.onInitializeAccessibilityNodeInfo(AccessibilityDelegateCompat.java:89) at android.view.View.onInitializeAccessibilityNodeInfo(View.java:8609) at androidx.appcompat.widget.LinearLayoutCompat.onInitializeAccessibilityNodeInfo(LinearLayoutCompat.java:1794) at android.view.View.createAccessibilityNodeInfoInternal(View.java:8570) at android.view.View$AccessibilityDelegate.createAccessibilityNodeInfo(View.java:29784) at android.view.View.createAccessibilityNodeInfo(View.java:8553) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1271) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1294) at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchAccessibilityNodeInfos(AccessibilityInteractionController.java:1096) at android.view.AccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdUiThread(AccessibilityInteractionController.java:342) at android.view.AccessibilityInteractionController.access$400(AccessibilityInteractionController.java:75) at android.view.AccessibilityInteractionController$PrivateHandler.handleMessage(AccessibilityInteractionController.java:1460) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7680) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:423) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
这个堆栈完全没有指向我的业务代码,我在多台设备上测试都无法复现。崩溃看起来和无障碍功能相关,但我只遵循了常规无障碍开发规范,没有做过特殊处理。想请教可能的排查方向。
更新 [2025-08-24]
我已经确认崩溃发生在应用Activity退出后,通过添加标记跟踪Activity状态得知。该崩溃由Thread.UncaughtExceptionHandler捕获,我认为这是系统bug,没有实际危害。
排查方向建议
- 升级Material Components库:崩溃发生在
NavigationMenuPresenter的内部适配器中,很可能是旧版本库存在无障碍场景下的线程安全或生命周期兼容问题,尝试升级到最新稳定版的Material库,看官方是否已经修复该问题。 - 检查Activity销毁时的菜单数据操作:排查Activity退出过程中,是否有异步线程在修改导航菜单的数据源(比如
onDestroy之后仍有网络回调更新菜单列表),导致无障碍服务访问时列表长度已经变化,引发索引越界。 - 模拟无障碍场景测试:开启TalkBack、屏幕阅读器等无障碍服务后,快速执行Activity退出操作(比如连续按返回键),高频触发场景下可能复现崩溃,因为无障碍框架的回调可能在Activity生命周期后期仍在执行。
- 过滤全局异常上报:既然确认崩溃发生在Activity退出后且无实际影响,可以在全局异常处理器中添加过滤规则,忽略这类来自Material内部且发生在Activity销毁后的崩溃,避免干扰统计数据。
- 统计系统版本分布:查看崩溃上报的设备系统版本,看是否集中在特定Android版本(比如Android 11/12),部分系统版本的无障碍框架可能存在兼容性bug,针对性测试该版本设备。
内容的提问来源于stack exchange,提问作者Hong
相关产品推荐
相关产品推荐

