Map item index in lazy column to item index in list

2.3k Views Asked by At

So I have a marketplace list similar to the code snippet attached. We have a list of marketplace items in the viewmodel being observed as our state. We break down each marketplace item into a lazyitem (side question, does this improve performance, over, say a column, batching all the composables together into one?).

The question I have is a way to map the actual index of each lazy item to the percieved item index, ideally without providing the lazylist state to each composable child (for reusability and/or performance). In the following example, if I were to have two marketplace items in my list, the second without any mediaData, the map should have the following:

0 -> 0

1 -> 0

2 -> 0

3 -> 0

4 -> 1

5 -> 1

6 -> 1

    // this is the state value I want to fill as the lazycolumn gets built
    var perceivedIndexMapper by remember { mutableStateOf(mapOf<Int, Int>()) } 

    var listState = rememberLazyListState()
    val marketplaceItems by viewModel.items.collectAsState() // List items flow

    LazyColumn(
        state = listState
    ) {
       marketplaceItems.forEachIndexed { marketplaceItem, index ->
          item {
             Header(marketplaceItem.headerData, index)
          }
          item {
             Body(marketplaceItem.bodyData, index)
          }

          // Some marketplace items don't have media
          marketplaceItem.mediaData?.let {
             item {
                Media(marketplaceItem.mediaData, index)
             }
          }
          item {
             Footer(marketplaceItem.footerData, index)
          }
       }
    }
1

There are 1 best solutions below

0
On

check this

// this is the state value I want to fill as the lazycolumn gets built
var perceivedIndexMapper by remember { mutableStateOf(mapOf<Int, Int>())} 

var listState = rememberLazyListState()
val marketplaceItems by viewModel.items.collectAsState()

LazyColumn(
    state = listState
) {
   itemsIndexed(marketplaceItems) { index, item ->
           Header(marketplaceItem.headerData, index)
           Body(marketplaceItem.bodyData, index)
           item.mediaData?.let {
               Media(marketplaceItem.mediaData, index)
               perceivedIndexMapper.put(index, 0)
           }
           Footer(marketplaceItem.footerData, index)
           
           if(item.mediaData == null) {
               perceivedIndexMapper.put(index, 1)
           }
    }
}

Note

You should understand exactly how the LazyList works! The code above will display as many products as you need and meet the criteria you set. You have one index per product with 0 map value for media and 1 without media. Also you should get this mutable state in another composable function for reuse (State hoisting)

I hope, I helped you