I have a LazyColumn where I am displaying items from my DB, items are based on selected date when date changes items size changes and then app crashes with IndexOutOfBoundException here is the code
getting items form viewModel
val allMedicines by viewModel.getMedicineByTime(selectedDateMillis).collectAsStateWithLifecycle(initialValue = emptyList())
and lazy column code is as follows
if (allMedicines.isEmpty()) {
AnimateLottieRaw(resId = R.raw.empty_box, modifier = Modifier.size(200.dp))
Text(
text = "No Medicines scheduled for today\ntry adding some using the + button below",
modifier = Modifier.fillMaxSize(),
fontFamily = dmSansFont,
textAlign = TextAlign.Center,
)
} else {
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(allMedicines) { medicine ->
MedicineCard(medicine = medicine) {
onEvent(ClickEvents.EditMedicine(it))
}
}
}
}
I am facing this error only when lazyColumn needs to recompose if I make selected date constant and give a particular date then there is no issue but when I make it so that user clickEvent changes selected date it will crash, so please give me any solution or any hint
I have used some log statements to check if the list is getting updated and yes it's size is getting updated, I have tried to change lazyColumn to work with item size rather than actual list the code for that is as follows
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(allMedicines.size) { pos ->
val medicine = allMedicines[pos]
MedicineCard(medicine = medicine) {
onEvent(ClickEvents.EditMedicine(it))
}
}
}
but still not use
EDIT: I have replaced lazyColumn with a text and just displayed size of the items when date gets updated and it is working fine and displaying the items scheduled on that particualr date, so in my POV the issue here is not with the DB or the viewModel.
EDIT 2: for the time being I have removed the LazyColumn and replaced it with a normal column while iterating all Medicines manually, I know this isn't the way to do it but as a temporary measure, I had to do this, the code is as follows
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
allMedicines.forEach {
MedicineCard(medicine = it) {
onEvent(ClickEvents.EditMedicine(it))
}
}
}
this is just a temporary solution and it is working fine as of now so the issue here is with lazyColumn I guess, please let me know of any solution or at least any sort of hint that might lead to a better solution
pastebin link for the error log
My guess is that the list elements themselves and the size
field of the list are not updated at the exact same time, so the list might already be shorter for a moment, but the size value still displays the old length, The LazyColumn
then tries to display a position in your allMedicines
list that actually does no longer exist, resulting in an IndexOutOfBoundsException
.
I suggest that if you need the index of the position of the item in the LazyColumn
, use itemsIndexed
instead:
LazyColumn(modifier = Modifier.fillMaxSize()) {
itemsIndexed(allMedicines) { index, medicine ->
MedicineCard(medicine = medicine) {
onEvent(ClickEvents.EditMedicine(index))
}
}
}
Note that the items
function itself offers different parameters. The documentation mentions three variants:
items
with providing a countitems
with providing an Arrayitems
with providing a ListEdit: As the answer below suggests, there is a bug in Jetpack Compose. It has been reported in the Google Issue Tracker, recently fixed and published with Compose Foundation Version 1.6.0-beta01. You can include it with the following dependency:
dependencies {
implementation("androidx.compose.foundation:foundation:1.6.0-beta01")
}
Please update new version 1.6.0-beta01 of compose foundation if you are using verion 1.6.0-alpha08 that exist issue about the children of SubcomposeLayout.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With