Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Application crash due to IndexOutOfBoundsException in Lazycolumn Jetpack compose

I am getting IndexOutOfBoundsException when I remove items in mutableStateListOf<MyType>, where MyType is some custom Type. There are almost around 250 items in myList. The items are removed in a loop. Almost 6 elements are visible in viewport at one time. When the item count reaches less than or equal to 6 (with scroll position at top) then this exception is raised and the application crashes.

Furthermore, the application is crashed only when ListView is the active screen. Otherwise it does not crash/this IndexOutOfBoundsException is not raised. I have debugged the application logic and made sure that there are checks to ignore any update/add/remove request with index larger than list size. I suspect the exception is raised during recomposition only. Another behaviour I observed is when the List is scrolled to the bottom and the items are removed, then this exception is already raised at the very beginning of the loop. Please have a look at the stack trace.

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)
    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)`

I am using the following jetpack compose version:

ext.composeCompilerVersion = 1.4.3

ext {
    compose_version = composeCompilerVersion //COMPOSE COMPILER VERSION
}

Following is the example composable function for displaying 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()
}

I tried reproducing the behaviour. First thing I found out was that this exception is not raised if ListView is not the active screen (because ListView is not recomposed). Also after looking at the stack trace my assumption is that this issue has something to do with the internal jetpack compose libraries or the way I have implemented the composable function i.e. Lazycolumn.

like image 782
Mansoor Avatar asked Dec 06 '25 02:12

Mansoor


1 Answers

This issue has been resolved in foundation-android:1.6.0-beta01.

https://developer.android.com/jetpack/androidx/releases/compose-foundation#1.6.0-beta 01

like image 60
CAIOS Avatar answered Dec 08 '25 09:12

CAIOS



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!