Skip to main content

Introduction

note

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 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 mandatory 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 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: