Introduction
Lazy Collections are a Kotlin-only API. Within Litho, lists are implemented using the Lazy Collection API.
For Java use, or docs on the older Java Spec-based Sections API, see Sections Basics in the 'Spec APIs' section.
Lazy Collection basicsβ
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:
The following code 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 optionalid
parameter - ifid
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 mandatoryid
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 a user with 100 friends. During the resolution of the Column
, the associated 100 Text
components would also be resolved despite only a few being visible on the screen initially. 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.
Documentation contentβ
The documentation for lists includes the following pages:
- Layout and Styling - how to customize the rendering of a list.
- Interactions - how to interact with and listen to events on a list.
- Working with Updates - how to ensure a list handles updates efficiently.
- Sections Migration Guide - guidance for migrating an existing list rendered with Sections to Lazy Collections.