What the key parameter in LazyColumn is actually doing | A deep dive
Tags: android, mobile, kotlin, tristan
Published: 2023-11-10 15:33:14

### Table of contents
1. [Introduction](#intro)
2. [What should be recomposed?](#re)
3. [The solution to this is the key composable](#key)
4. [Resources](#res)

### My app on the Google play store
- [The app](https://play.google.com/store/apps/details?id=elliott.software.clicker)


### Introduction <a name="intro"></a>
- I originally posted this on stack overflow, [HERE](https://stackoverflow.com/questions/68790215/lazycolumn-items-key-parameter-purpose/77461021#77461021)

- This is a bit of a deep dive I did after reading the [Lifecycle of composables documentation](https://developer.android.com/jetpack/compose/lifecycle). I would highly recommend that you read that documentation as it will give you a deeper understanding on what the heck goes on in compose

- This is an intermediate level post. However, if you are a beginner I still think you could benefit from reading this blog post

### What should be recomposed? <a name="re"></a>
- When considering what composable should be recomposed, the compose compiler fist checks each distinct composable. We can use the [documentation](https://developer.android.com/jetpack/compose/lifecycle#composition-anatomy) to define `distinct` as:

`The instance of a composable in Composition is identified by its call site. The Compose compiler considers each call site as distinct. Calling composables from multiple call sites will create multiple instances of the composable in Composition.`

**call site** : `is the source code location in which a composable is called. This influences its place in Composition, and therefore, the UI tree`

- so basically a composable is `distinct` if it is called in different spots in your code, even if the composables are the same:
```
Column {  
    YourComposable()
    YourComposable() 
    }
```
- Both instance of `YourComposable()` are considered `distinct` by the compiler
- So if a composable is `distinct`(called from different places in your code) the compose compiler will know to only recompose the composable that has a state change

- However, what happens when you have a for loop like this:
```
@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            // MovieOverview composables are placed in Composition given its
            // index position in the for loop
            MovieOverview(movie)
        }
    }
}

```
- `MovieOverview` is being called from the same `call site`(not distinct). To combat this scenario the compose compiler will use the `execution order in addition to the call site to keep the instances distinct`

- This will work fine as long as values are only removed and added to the bottom of the list(index of length-1). But once the list changes by either adding to the top or the middle of the list. Or by removing or reordering items ,it'll cause a recomposition in all MovieOverview calls whose input parameter has changed position in the list

- if you have a list of length 100 and you insert at item at index 50, then all the composables from index 99-50 will get recomposed even though they have not had their state changed

### The solution to this is the key composable <a name="key"></a>
- the [key composable](https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#key(kotlin.Array,kotlin.Function0)) allows the compose compiler to identify each composable as distinct and eliminate the wasteful recompositions
- the `key` must be unique to the list and will crash if it is not
```
@Composable
fun MoviesScreenWithKey(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            key(movie.id) { // Unique ID for this movie
                MovieOverview(movie)
            }
        }
    }
}

```
- The code block above can now have its items, rearranged, removed and added to at any index and no wasteful recompositions will occur.

### What is the LazyColumn items key parameter purpose ?
- It serves the exact same role. LazyColumn just has built-in support for the key composable
```
@Composable
fun MoviesScreenLazy(movies: List<Movie>) {
    LazyColumn {
        items(movies, key = { movie -> movie.id }) { movie ->
            MovieOverview(movie)
        }
    }
}

```
- If we did not provide the `key` and tried to remove, add or reorganize we would face the exact same wasteful recompositions mention earlier

### Resources <a name="res"></a>
[Lifecycle of composables documentation](https://developer.android.com/jetpack/compose/lifecycle)


### Conclusion 
- Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on [Twitter](https://twitter.com/AndroidTristan).