I’m building a simple Food Manager screen using Jetpack Compose. The UI allows users to:
Select a food category (Fruit, Vegetable, Snack, Drink).
Select an item from that category.
Add the selection to a cart.
Display the cart using a LazyColumn.
The code works fine functionally, but I’m facing a performance issue:
Scrolling the LazyColumn does not feel as smooth as RecyclerView.
When multiple items are added, UI performance drops.
@Composable fun FoodManager() { Scaffold( modifier = Modifier.fillMaxSize() ) { innerPadding -> Column( modifier = Modifier.padding(innerPadding), ) { // Expanded states var categoryExpanded by remember { mutableStateOf(false) } var itemExpanded by remember { mutableStateOf(false) } var addToCart by remember { mutableStateOf(false) } // Selected values var selectedCategory by remember { mutableStateOf("") } var selectedItem by remember { mutableStateOf("") } // Field sizes var categoryTextFieldSize by remember { mutableStateOf(Size.Zero) } var itemTextFieldSize by remember { mutableStateOf(Size.Zero) } val cartList = remember { mutableStateListOf<Pair<String, String>>() } // Categories val categories = listOf("Fruit", "Vegetable", "Snack", "Drink") // Map of items val itemsMap = mapOf( "Fruit" to listOf("Apple", "Banana", "Mango", "Orange"), "Vegetable" to listOf("Potato", "Tomato", "Onion", "Carrot"), "Snack" to listOf("Chips", "Burger", "Sandwich"), "Drink" to listOf("Water", "Juice", "Soda", "Tea") ) Text( "Food Manager", textAlign = TextAlign.Center, fontSize = 20.sp, modifier = Modifier .fillMaxWidth() .padding(10.dp) ) Row( modifier = Modifier .fillMaxWidth() .padding(10.dp) ) { // First dropdown (Category) Box(modifier = Modifier.weight(1f)) { OutlinedTextField( value = selectedCategory, onValueChange = { selectedCategory = it }, readOnly = true, trailingIcon = { Icon( if (categoryExpanded) Icons.Default.KeyboardArrowUp else Icons.Default.KeyboardArrowDown, contentDescription = null, modifier = Modifier.clickable { categoryExpanded = !categoryExpanded } ) }, placeholder = { Text("Select Category", fontSize = 12.sp) }, modifier = Modifier .fillMaxWidth() .onGloballyPositioned { coordinates -> categoryTextFieldSize = coordinates.size.toSize() } ) DropdownMenu( expanded = categoryExpanded, onDismissRequest = { categoryExpanded = false }, modifier = Modifier.width(with(LocalDensity.current) { categoryTextFieldSize.width.toDp() }) ) { categories.forEach { category -> DropdownMenuItem( text = { Text(category) }, onClick = { selectedCategory = category selectedItem = "" // reset item when category changes categoryExpanded = false } ) } } } Spacer(modifier = Modifier.width(20.dp)) // Second dropdown (Items) Box(modifier = Modifier.weight(1f)) { OutlinedTextField( value = selectedItem, onValueChange = { selectedItem = it }, readOnly = true, trailingIcon = { Icon( if (itemExpanded) Icons.Default.KeyboardArrowUp else Icons.Default.KeyboardArrowDown, contentDescription = null, modifier = Modifier.clickable { itemExpanded = !itemExpanded } ) }, placeholder = { Text("Select Item", fontSize = 12.sp) }, modifier = Modifier .fillMaxWidth() .onGloballyPositioned { coordinates -> itemTextFieldSize = coordinates.size.toSize() } ) DropdownMenu( expanded = itemExpanded, onDismissRequest = { itemExpanded = false }, modifier = Modifier.width(with(LocalDensity.current) { itemTextFieldSize.width.toDp() }) ) { val itemList = itemsMap[selectedCategory] ?: emptyList() itemList.forEach { item -> DropdownMenuItem( text = { Text(item) }, onClick = { selectedItem = item itemExpanded = false } ) } } } } val context = LocalContext.current Button( onClick = { if (selectedCategory.isNotEmpty() && selectedItem.isNotEmpty()) { val pair = Pair(selectedCategory, selectedItem) if (cartList.contains(pair)) { Toast.makeText(context, "Already added!", Toast.LENGTH_SHORT).show() } else { cartList.add(pair) addToCart = true } } }, modifier = Modifier .fillMaxWidth() .align(Alignment.CenterHorizontally) .padding(10.dp) ) { Text("Add To Card") } Log.d("TAG", "FoodManager: ${addToCart}") if (addToCart == true) { LazyColumn(modifier = Modifier.fillMaxSize()) { items(cartList, key = { it.hashCode() }) { selecteditem -> ListView(category = selecteditem.first, items = selecteditem.second) } } } } } } @Composable fun ListView(category: String, items: String) { Card( modifier = Modifier .fillMaxWidth() .padding(16.dp), elevation = CardDefaults.cardElevation(defaultElevation = 24.dp), colors = CardDefaults.cardColors( containerColor = Color(0xFF00BCD4) ) ) { Text(text = category + ": " + items, modifier = Modifier.padding(16.dp)) } }