Skip to main content

Introduction

note

Lazy Collections are a Kotlin-only API. If you're using Java or looking for docs on the older Java codegen-based Sections API, see here.

Lazy Collections are components that can efficiently render a scrollable list of child components using Android's RecyclerView. The 'lazy' in the name refers to the fact that not all children need to be immediately resolved to put content on the screen. Instead, a Lazy Collection maintains a window of resolved children which is dynamically updated while scrolling.

Lazy Collections are available as follows:

Lazy Collection Basics​

The following example creates a LazyList and adds a child Text component for each list item.

class FriendLazyList(private val friends: List<Person>) : KComponent() {
override fun ComponentScope.render(): Component = LazyList {
children(friends, id = { it.id }) { Text(it.name) }
}
}

Adding Children​

An important difference from adding children in a normal container like Column is that each child needs a consistent and unique id. This id is used to detect moves, insertions, deletions, and updates across render passes.

There are two primary ways to add children to a Lazy Collection:

  • child: takes a component and an optional id parameter - if id is null or not provided, an id will be generated based on the sequence and type of this child in the list (i.e. 'third Text'). This auto-generated id may be fine, but an explicit one is safer!
  • children: takes a lambda mapping a list of data to a list of components and a mandataory id function that maps data to an id for that component.

For more information on how to make sure updates are applied to your Lazy List correctly and efficiently, see the Working with Updates docs.

Why not just use Column or Row?​

A simple, but non-scalable approach to render a list of components is to use a Column or Row container:

class FriendsColumn(private val friends: List<Person>) : KComponent() {
override fun ComponentScope.render(): Component = VerticalScroll {
Column { friends.forEach { friend -> child(Text(friend.name)) } }
}
}

The above component creates a Column and adds a child Text component for each friend: it's made scrollable by wrapping it in a VerticalScroll.

This approach is inefficient and inflexible when dealing with many items.

Consider if there were 100 friends. During the resolution of the Column, you would also eagerly resolve 100 Text components, despite only a few being initially visible on the screen. Additionally, if one of the names was updated or changed position, all 100 Text components would be resolved again.

A more efficient and flexible approach is to use Lazy Collections.

Next Steps​

  • Layouts: check out the next page to learn about how to customize the rendering of your list.
  • Interactions: check out docs on list interactions to learn about how to interact with and listen to events on your list.
  • Performance: check out the docs on working with updates to learn about how to make sure your list handles updates efficiently.
  • Migrating from Sections: if you're migrating an existing list from the Sections API, checkout docs to aid your migration.