You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级Android Compose至alpha08后LazyColumn触发IndexOutOfBoundsException问题咨询

Compose Alpha07升级Alpha08后LazyColumn触发IndexOutOfBoundsException问题解析

问题确认

不少开发者在将Android Compose从alpha07版本升级到alpha08后,遇到LazyColumn抛出IndexOutOfBoundsException的情况,典型报错堆栈如下:

Process: com.my.application, PID: 4397
 java.lang.IndexOutOfBoundsException: Index 4, size 4
    at androidx.compose.foundation.lazy.layout.MutableIntervalList.checkIndexBounds(IntervalList.kt:183)
    at androidx.compose.foundation.lazy.layout.MutableIntervalList.get(IntervalList.kt:166)
    at androidx.compose.foundation.lazy.layout.LazyLayoutIntervalContent.getKey(LazyLayoutIntervalContent.kt:86)
    at androidx.compose.foundation.lazy.LazyListItemProviderImpl.getKey(LazyListItemProvider.kt:85)
    at androidx.compose.foundation.lazy.LazyListMeasuredItemProvider.getAndMeasure(LazyListMeasuredItemProvider.kt:46)
    at androidx.compose.foundation.lazy.LazyListMeasureKt.createItemsAfterList(LazyListMeasure.kt:418)
    at androidx.compose.foundation.lazy.LazyListMeasureKt.measureLazyList-50ZNEM8(LazyListMeasure.kt:278)
    at androidx.compose.foundation.lazy.LazyListKt$rememberLazyListMeasurePolicy$1$1.invoke-0kLqBqw(LazyList.kt:328)
    at androidx.compose.foundation.lazy.LazyListKt$rememberLazyListMeasurePolicy$1$1.invoke(LazyList.kt:193)
    at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$3$2$1.invoke-0kLqBqw(LazyLayout.kt:107)
    at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$3$2$1.invoke(LazyLayout.kt:100)
    at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:708)
    at androidx.compose.ui.node.InnerNodeCoordinator$LookaheadDelegateImpl.measure-BRTryo0(InnerNodeCoordinator.kt:81)
    at androidx.compose.foundation.AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2.invoke-3p2s80s(AndroidOverscroll.kt:584)
    at androidx.compose.foundation.AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2.invoke(AndroidOverscroll.kt:583)
    at androidx.compose.ui.layout.LayoutModifierImpl.measure-3p2s80s(LayoutModifier.kt:291)
    at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:64)
    at androidx.compose.foundation.AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1.invoke-3p2s80s(AndroidOverscroll.kt:568)
    at androidx.compose.foundation.AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1.invoke(AndroidOverscroll.kt:567)
    at androidx.compose.ui.layout.LayoutModifierImpl.measure-3p2s80s(LayoutModifier.kt:291)
    at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:64)
    at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:646)
    at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:64)
    at androidx.compose.foundation.layout.FillNode.measure-3p2s80s(Size.kt:699)
    at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:64)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performLookaheadMeasure$1.invoke(LayoutNodeLayoutDelegate.kt:1622)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performLookaheadMeasure$1.invoke(LayoutNodeLayoutDelegate.kt:1621)
    at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2303)
    at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:496)
    at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256)
    at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
    at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:111)
    at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release$default(OwnerSnapshotObserver.kt:105)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performLookaheadMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1621)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performLookaheadMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
    at androidx.compose.ui.node.LayoutNodeLayoutDelegate$LookaheadPassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1289)
    at androidx.compose.ui.node.LayoutNode.lookaheadRemeasure-_Sx5XlM$ui_release(LayoutNode.kt:1126)
    at androidx.compose.ui.node.LayoutNode.lookaheadRemeasure-_Sx5XlM$ui_release$default(LayoutNode.kt:1120)
    at androidx.compose.ui.node.MeasureAndLayoutDelegate.doLookaheadRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:313)
    at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:478)
    at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded$default(MeasureAndLayoutDelegate.kt:461)
    at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:354)
    at androidx.compose.ui.platform.AndroidComposeView.measureAndLayout(AndroidComposeView.android.kt:969)
    at androidx.compose.ui.node.Owner.measureAndLayout$default(Owner.kt:230)
    at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1222)
    at android.view.View.draw(View.java:23892)
    at android.view.View.updateDisplayListIfDirty(View.java:22756)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
    at android.view.View.updateDisplayListIfDirty(View.java:22712)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
    at android.view.View.updateDisplayListIfDirty(View.java:22712)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
    at android.view.View.updateDisplayListIfDirty(View.java:22712)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
    at android.view.View.updateDisplayListIfDirty(View.java:22712)
    at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:694)
    at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:700)
    at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:798)
    at android.view.ViewRootImpl.draw(ViewRootImpl.java:4939)
    at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4643)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3822)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2465)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9305)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1339)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348)
    at android.view.Choreographer.doCallbacks(Choreographer.java:952)
    at android.view.Choreographer.doFrame(Choreographer.java:882)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1322)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8177)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

已知根因

该问题属于Compose alpha08版本的已知bug,核心原因是LazyColumn的布局测量逻辑与数据源更新之间存在竞态:当LazyColumn正在执行测量流程时,数据源发生了长度缩减的变化,而MutableIntervalList的索引检查逻辑在alpha08的更新中变得更严格,没有处理这种异步修改的场景,最终触发越界异常。

临时解决方案

  • 回退到Compose alpha07版本,等待官方发布修复版本
  • 确保LazyColumn的每个item都设置唯一且稳定的key,避免因item复用导致的索引混乱
  • 禁止在Compose重组过程中异步修改LazyColumn的数据源,所有数据更新操作需在主线程执行,并通过StateFlow、MutableState等Compose官方状态管理工具触发重组
  • 临时添加数据源长度校验:在LazyColumn渲染前判断数据源长度是否大于0,或在数据更新时添加短暂延迟(仅作为临时应急方案,不推荐长期使用)

内容的提问来源于stack exchange,提问作者Hector

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 21:48:10