0

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)
          }
       }
    }
4
  • I can't understand why you should use a Map, or why itemsIndexed() is not enough Commented Dec 14, 2022 at 17:36
  • itemsIndexed would have a single lazy item for each dataitem we have, however, We want to break down the data model to have mutliple list items per single model. I know we should do this decomposition in the viewmodel or repository layer, but unfortunately, that's not the way the codebase was set up. Commented Dec 14, 2022 at 17:41
  • In you example you just adding a Header and a Body for each marketplaceItem. Why don't use them together in a single item? Commented Dec 14, 2022 at 17:46
  • @GabrieleMariotti I simplified my use case in the example. In my actual use case, the data models are much more complex, and the items have many more components. Commented Dec 14, 2022 at 18:30

1 Answer 1

0

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.