0Pricing
Android Academy · Урок

Зачем нужна постраничная загрузка

Цена загрузки всех данных одновременно

«Зачем нужна постраничная загрузка» — бесплатный урок Android Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 4 уроков всего.

Загрузка всех данных обходится дорого

Представьте ленту из 50 000 элементов. Если загрузить и хранить их все сразу, вы потратите лишнюю память, замедлите сеть и заморозите интерфейс на время разбора ответа.

Большинство пользователей просматривают только первые несколько экранов. Постраничная загрузка означает загрузку данных небольшими частями (страницами) по мере прокрутки, а не всех данных сразу.

Проблема в коде

Наивный подход загружает весь список в память. Даже если сервер это поддерживает, ответ может быть огромным, а разобранный список занимает большую часть кучи.

Такой подход не масштабируется и на больших наборах данных может привести к OutOfMemoryError.

// Anti-pattern: load the whole table at once
suspend fun loadAllArticles(): List<Article> {
    // Could be tens of thousands of rows / megabytes of JSON
    return api.getArticles(limit = 50_000)
}

// UI holds ALL of them in memory at once
val articles = loadAllArticles()
LazyColumn {
    items(articles) { article -> ArticleRow(article) }
}

Как выглядит страница

Страница — это небольшой фрагмент набора данных, обычно от 20 до 50 элементов. Сервер возвращает одну страницу и указатель на следующую страницу — число, смещение или токен.

Приложение хранит в памяти только несколько страниц и удаляет старые, когда пользователь прокручивает список дальше.

data class ArticlePage(
    val items: List<Article>,
    val nextKey: Int?   // null means no more pages
)

// Example REST call returning one page
suspend fun getArticlePage(page: Int, size: Int = 20): ArticlePage

Знакомство с Paging 3

Paging 3 — это библиотека Jetpack, которая берет на себя все сложные задачи, связанные с постраничной загрузкой:

  • запрос следующей страницы, когда пользователь приближается к концу списка;
  • хранение в памяти только ограниченного диапазона элементов;
  • предоставление состояний загрузки и ошибки;
  • встроенная поддержка корутин, Flow и Jetpack Compose.

Добавление зависимости

Paging 3 поставляется в виде отдельных артефактов: среды выполнения и интеграции с Compose. Добавьте их в файл build.gradle.kts вашего модуля.

Артефакт paging-compose предоставляет вспомогательные средства для LazyColumn.

// build.gradle.kts (module)
dependencies {
    val pagingVersion = "3.3.6"
    implementation("androidx.paging:paging-runtime:$pagingVersion")
    implementation("androidx.paging:paging-compose:$pagingVersion")
}

Три основных компонента

Paging 3 строится вокруг трех типов, которые вы будете использовать снова и снова:

  • PagingSource — знает, как загрузить одну страницу из источника;
  • Pager — настраивает и создает поток постранично загружаемых данных;
  • PagingData — контейнер элементов, выдаваемых как Flow.

В следующих уроках мы создадим каждый из них.

PagingData и Flow

Ваш репозиторий предоставляет Flow<PagingData<T>>. Интерфейс собирает этот поток и отображает все элементы, загруженные к текущему моменту.

Вам не нужно самостоятельно собирать полный список — Paging передает элементы в интерфейс по мере необходимости.

import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow

class ArticleRepository(private val api: ArticleApi) {
    fun articles(): Flow<PagingData<Article>> = Pager(
        config = PagingConfig(pageSize = 20)
    ) {
        ArticlePagingSource(api)
    }.flow
}

PagingConfig управляет диапазоном данных

PagingConfig настраивает способ загрузки и хранения данных в Paging:

  • pageSize — количество элементов в одном запросе страницы;
  • prefetchDistance — расстояние до края списка, при котором запускается следующая загрузка;
  • enablePlaceholders — показывать места-заполнители для еще не загруженных элементов;
  • maxSize — максимальное количество элементов, хранящихся в памяти.
import androidx.paging.PagingConfig

val config = PagingConfig(
    pageSize = 20,
    prefetchDistance = 5,
    enablePlaceholders = false,
    maxSize = 100
)

Сеть или база данных — или и то и другое

PagingSource может получать данные из REST API, базы данных Room или любого другого пользовательского источника.

Для полноценной работы без подключения к сети можно объединить оба источника с помощью RemoteMediator (он рассматривается в последнем уроке): сеть заполняет локальную базу данных, а интерфейс загружает страницы из этой базы.

Плавная прокрутка и меньше памяти

При постраничной загрузке прокрутка остается плавной, поскольку каждый запрос небольшой, а размер хранящегося в памяти диапазона ограничен параметром maxSize.

Индикаторы загрузки и ошибки предоставляются автоматически через LoadState, поэтому вы можете показывать индикатор внизу или кнопку повтора без ручного управления состояниями.

// LoadState exposes loading/error per direction
when (val state = adapterLoadState.append) {
    is LoadState.Loading -> showBottomSpinner()
    is LoadState.Error -> showRetry(state.error)
    is LoadState.NotLoading -> hideBottomSpinner()
}

Когда нужна постраничная загрузка

Используйте Paging 3, когда:

  • набор данных большой или неограниченный — например, ленты, результаты поиска или история чата;
  • данные поступают из сетевого API, возвращающего страницы или курсоры;
  • вам нужны автоматический интерфейс загрузки и ошибок и контроль памяти.

Для короткого фиксированного списка, например меню настроек, обычный LazyColumn проще и вполне подходит.

Быстрая проверка

Какое основное преимущество дает использование Paging 3 для большого списка?

Итоги: зачем нужен Paging

Вы узнали, почему одновременная загрузка всех данных ухудшает производительность и увеличивает расход памяти, а также как Paging 3 решает эту проблему.

  • Данные загружаются небольшими страницами по мере прокрутки списка;
  • три основных компонента — PagingSource, Pager и PagingData;
  • PagingConfig настраивает размер страницы, предварительную загрузку и диапазон данных в памяти;
  • Paging интегрируется с корутинами, Flow и Compose и автоматически предоставляет состояния загрузки и ошибки.

Далее: создание PagingSource и подключение его к Pager.

Часто задаваемые вопросы

Урок «Зачем нужна постраничная загрузка» бесплатный?

Да — полный текст урока «Зачем нужна постраничная загрузка» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 4 уроков всего.

Чему я научусь в уроке «Зачем нужна постраничная загрузка»?

Цена загрузки всех данных одновременно Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Android Academy?

Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Зачем нужна постраничная загрузка»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Android Academy?

Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Зачем нужна постраничная загрузка
  2. PagingSource и Pager
  3. Постраничная загрузка в списках Compose
  4. RemoteMediator и кэширование
← Назад к Android Academy