提问人:Mansoor 提问时间:7/24/2023 更新时间:11/23/2023 访问量:1359
由于 Lazycolumn Jetpack compose 中的 IndexOutOfBoundsException 导致应用程序崩溃
Application crash due to IndexOutOfBoundsException in Lazycolumn Jetpack compose
问:
当我删除 mutableStateListOf 中的项目时,我得到 IndexOutOfBoundsException,其中 MyType 是一些自定义类型。myList 中大约有 250 个项目。这些项目在循环中被删除。视口中同时可见近 6 个元素。当项目计数小于或等于 6(滚动位置在顶部)时,将引发此异常,并且应用程序崩溃。
此外,仅当 Listview 是活动屏幕时,应用程序才会崩溃。否则它不会崩溃/不会引发此 indexoutofboundexception。我已经调试了应用程序逻辑,并确保有检查可以忽略索引大于列表大小的任何更新/添加/删除请求。我怀疑仅在重组期间才会引发异常。我观察到的另一种行为是,当列表滚动到底部并删除项目时,此异常已经在循环的一开始就引发了。请查看堆栈跟踪。
FATAL EXCEPTION: main Process: com.XXX.YYY.ZZZ, PID: 16225 java.lang.IndexOutOfBoundsException: Index 6, size 6 at androidx.compose.foundation.lazy.layout.MutableIntervalList.checkIndexBounds(IntervalList.kt:177) at androidx.compose.foundation.lazy.layout.MutableIntervalList.get(IntervalList.kt:160) at androidx.compose.foundation.lazy.layout.DefaultLazyLayoutItemsProvider.getKey(LazyLayoutItemProvider.kt:232) at androidx.compose.foundation.lazy.LazyListItemProviderImpl.getKey(Unknown Source:2) at androidx.compose.foundation.lazy.layout.DefaultDelegatingLazyLayoutItemProvider.getKey(LazyLayoutItemProvider.kt:201) at androidx.compose.foundation.lazy.LazyListItemProviderKt$rememberLazyListItemProvider$1$1.getKey(Unknown Source:2) at androidx.compose.foundation.lazy.LazyMeasuredItemProvider.getAndMeasure-ZjPyQlc(LazyMeasuredItemProvider.kt:46) at androidx.compose.foundation.lazy.LazyListMeasureKt.measureLazyList-Hh3qtAg(LazyListMeasure.kt:164) at androidx.compose.foundation.lazy.LazyListKt$rememberLazyListMeasurePolicy$1$1.invoke-0kLqBqw(LazyList.kt:299) at androidx.compose.foundation.lazy.LazyListKt$rememberLazyListMeasurePolicy$1$1.invoke(LazyList.kt:190) at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$1$2$1.invoke-0kLqBqw(LazyLayout.kt:71) at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$1$2$1.invoke(LazyLayout.kt:69) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:598) at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:103) at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:635) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:155) at androidx.compose.foundation.layout.SizeModifier.measure-3p2s80s(Size.kt:781) at androidx.compose.ui.node.BackwardsCompatNode.measure-3p2s80s(BackwardsCompatNode.kt:323) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:155) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasure$2.invoke(LayoutNodeLayoutDelegate.kt:1090) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasure$2.invoke(LayoutNodeLayoutDelegate.kt:1086) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2200) at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234) at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:230) at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341) at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:230) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:120) at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:107) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1086) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:342) at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release(LayoutNode.kt:1188) at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release$default(LayoutNode.kt:1179) at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:309) at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:434) 2023-07-03 15:30:55.228 16225-16225 AndroidRuntime com.com.XXX.YYY.ZZZ E at androidx.compose.ui.node.MeasureAndLayoutDelegate.access$remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:39) at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:330) at androidx.compose.ui.platform.AndroidComposeView.measureAndLayout(AndroidComposeView.android.kt:805) at androidx.compose.ui.node.Owner.measureAndLayout$default(Owner.kt:221) at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1035) at android.view.View.draw(View.java:21978) at android.view.View.updateDisplayListIfDirty(View.java:20852) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4552) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4525) at android.view.View.updateDisplayListIfDirty(View.java:20812) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4552) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4525) at android.view.View.updateDisplayListIfDirty(View.java:20812) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4552) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4525) at android.view.View.updateDisplayListIfDirty(View.java:20812) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4552) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4525) at android.view.View.updateDisplayListIfDirty(View.java:20812) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:581) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:587) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:664) at android.view.ViewRootImpl.draw(ViewRootImpl.java:3773) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3501) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2785) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1751) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7774) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:967) at android.view.Choreographer.doCallbacks(Choreographer.java:791) at android.view.Choreographer.doFrame(Choreographer.java:726) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7407) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
我正在使用以下喷气背包撰写版本:
'ext.composeCompilerVersion = 1.4.3
ext { compose_version = composeCompilerVersion //COMPOSE 编译器版本 }`
下面是用于显示 Listview 的可组合函数示例。
@Composable
fun ListViewInternalTest(
elements2: List<MyType>
) {
val listState = rememberLazyListState()
LazyColumn(
modifier = Modifier
.height(pixelToDp(pixelSize = 792))
.simpleVerticalScrollbar(state = listState),
state = listState
) {
items(
elements2.size
) { index ->
Column() {
Row(
modifier = Modifier
.padding(start = pixelToDp(pixelSize = 35))
.height(pixelToDp(pixelSize = 130)),
verticalAlignment = Alignment.CenterVertically
) {
if(index < elements2.size) {
val element = elements2.getOrNull(index)
if (element != null) {
Text(
modifier = Modifier
.align(Alignment.Center)
.width(pixelToDp(pixelSize = 202))
.alpha(1f),
text = "CH " + element.someMember.toString()
)
}
}
}
}
}
}
}
val myList = mutableStateListOf<MyType>()
fun insertItemToMyListAtIndex(index: Int, argMyType: MyType){
if(index >= 0 && index <= myList.size) {
myList.add(index, argMyType)
}
}
fun updateItemInMyListAtIndex(index: Int, argMyType: MyType) {
if(index>= 0 && index< myList .size) {
myList[index] = argMyType
}
}
fun removeItemFromMyList(index: Int) {
if(index >= 0 && index < myList.size) {
myList.removeAt(index)
}
}
fun clearAllitemsInMyList(){
myList.clear()
}
我试着重现这种行为。我发现的第一件事是,如果 ListView 不是活动屏幕,则不会引发此异常(因为 Listview 未重构)。此外,在查看堆栈跟踪后,我的假设是这个问题与内部 jetpack 组合库或我实现可组合函数(即 Lazycolumn)的方式有关。
答:
**在您的代码中,尝试使用以下代码并运行 **
@Composable
fun ListViewInternalTest(
elements2: List<MyType>
) {
val listState = rememberLazyListState()
LazyColumn(
modifier = Modifier
.height(pixelToDp(pixelSize = 792))
.simpleVerticalScrollbar(state = listState),
state = listState
) {
items(
elements2
) { index, element ->
Column() {
Row(
modifier = Modifier
.padding(start = pixelToDp(pixelSize = 35))
.height(pixelToDp(pixelSize = 130)),
verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier
.align(Alignment.Center)
.width(pixelToDp(pixelSize = 202))
.alpha(1f),
text = "CH " + element.someMember.toString()
)
}
}
}
}
}
}
}
此问题已在 foundation-android:1.6.0-beta01 中解决。
https://developer.android.com/jetpack/androidx/releases/compose-foundation#1.6.0-beta 01
评论