Как выбрать между Paging 2 и Paging 3 и безопасно мигрировать
Выбор очевиден для большинства проектов: Paging 3 — современный, производительный и Kotlin‑ориентированный стандарт; миграция обычно занимает 1–2 дня и описана ниже с готовыми шагами.
Ключевые отличия Paging 2 и Paging 3
- Архитектура:
- Paging 2: DataSource (PageKeyed/Positional) с callback‑подходом (loadInitial, loadAfter).
- Paging 3: единый PagingSource с suspend‑load, Pager и Flow. RemoteMediator для гибридного кэша (Room + сеть).
- Асинхронность:
- Paging 2 ориентирован на Java/Callback/RxJava2.
- Paging 3 — нативно Coroutines/Flow; поддерживает RxJava3, Combine.
- Кэш и синхронизация:
- Paging 2: ручная интеграция с Room/Retrofit.
- Paging 3: RemoteMediator упрощает инвалидацию, синхронизацию и кэширование.
- Обработка состояний:
- Paging 2: частично через PagedList и callback‑хуки.
- Paging 3: LoadState, LoadStateAdapter, удобная обработка loading/error/refresh.
- Производительность и стабильность:
- Paging 3 обычно быстрее и экономнее по памяти в реальных сценариях (особенно при сетевых запросах и больших списках).
Paging 3 — рекомендованный Google вариант в 2026: лучшая интеграция с Kotlin, упрощённый кэш и предсказуемые LoadState.
Что выбрать в 2026 году
Выбирайте Paging 3, если:
- Проект на Kotlin 1.6+ (особенно 1.9+) и вы используете Coroutines/Flow.
- Нужны Room + сеть (RemoteMediator значительно упрощает).
- Требуется масштабируемость и экономия памяти на больших списках.
Оставайтесь на Paging 2 только если:
- У вас большой, стабильный Java‑проект без планов на Kotlin/Coroutines.
- Вы не хотите тратить ресурсы на миграцию и фичи Paging 3 не нужны.
Если планируете долгосрочную поддержку и новые фичи (Compose, MPP), откладывать миграцию не рекомендуется — Paging 3 остаётся приоритетом.
Пошаговая миграция с Paging 2 на Paging 3
Оценочно: 1–2 дня для среднего проекта. Основные шаги:
- Обновите зависимости (пример для марта 2026):
implementation "androidx.paging:paging-runtime-ktx:3.3.2"
implementation "androidx.paging:paging-compose:3.3.2" // если Compose
- Переведите DataSource → PagingSource:
- Замените PageKeyedDataSource/PositionalDataSource на класс, наследующий PagingSource<Key, Value>.
- Реализуйте suspend fun load(params: LoadParams
): LoadResult<Key, Value>.
Пример:
class MyPagingSource(private val repo: Repo) : PagingSource<Int, Item>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Item> {
return try {
val page = params.key ?: 1
val data = repo.fetch(page, params.loadSize)
LoadResult.Page(data.items, prevKey = data.prev, nextKey = data.next)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
}
- Создайте Pager и получайте Flow:
val flow: Flow<PagingData<Item>> = Pager(
config = PagingConfig(pageSize = 20, enablePlaceholders = false),
pagingSourceFactory = { MyPagingSource(repo) }
).flow
- Добавьте RemoteMediator при кэше через Room:
- Реализуйте RemoteMediator<Key, Entity>, в load() синхронизируйте сеть и БД, используйте с Room PagingSource.
- Обновите UI:
- Замените PagedListAdapter на PagingDataAdapter.
- Подписка:
lifecycleScope.launch {
viewModel.pagingFlow
.cachedIn(viewModelScope) // обязательно
.collectLatest { adapter.submitData(it) }
}
- Добавьте LoadStateAdapter для footer/header, обработку refresh/loading/error.
Не забывайте cachedIn(viewModelScope) — без него данные не кэшируются корректно и возможны лишние запросы при пересоздании UI.
- Тестирование:
- Проверяйте сценарии offline, empty state, retry.
- Тестируйте производительность на больших списках и переключения конфигурации.
Частые ошибки
- Забыт cachedIn — приводит к повторным загрузкам и утечкам.
- Неправильная логика nextKey/prevKey — результаты могут зацикливаться.
- Игнорирование LoadState — пользователи не увидят ошибки/индикацию загрузки.
- Использование PagingSource как синглтона — PagingSource должен создаваться заново в pagingSourceFactory.
FAQ
- Нужно ли мигрировать прямо сейчас?
- Если проект активно развивается и использует Kotlin/Room/Retrofit — да. Для холодного Java‑проекта можно отложить, но планируйте миграцию в будущем.
- Можно ли использовать Paging 3 с RecyclerView в Java?
- Да, но вы потеряете часть синтаксического удобства Coroutines/Flow; API всё ещё совместимо с RecyclerView.
- Стоит ли ждать Paging 4?
- Paging 4 может добавить Compose MPP‑фичи, но Paging 3 актуален и поддерживается: мигрируйте сейчас, чтобы получить выгоды уже сегодня.
Если нужно, приложу конкретный пример миграции вашего DataSource → PagingSource или ревью кода миграции.