Modern Android Pagination: Efficient List Rendering with Jetpack Paging 3
TL;DR: Jetpack Paging 3 makes it easy to load and display large data sets in Android apps efficiently. This guide covers setup, usage, best practices, and common pitfalls for high-performance pagination.
Cover Image
[ADD IMAGE - Cover]
Suggestion: A modern Android UI displaying a scrolling list with a loading spinner at the bottom.
Alt text: Android list with pagination using Jetpack Paging 3
Table of Contents
- Introduction to Jetpack Paging 3
- Why Use Paging 3?
- Setting Up Paging 3 in Your Project
- Implementing a PagingSource
- Integrating with ViewModel & Repository
- Displaying Data in RecyclerView
- Handling Loading & Error States
- Best Practices for Performance
- Common Mistakes to Avoid
- Conclusion & Further Reading
1) Introduction to Jetpack Paging 3
Loading large datasets in Android can easily lead to memory issues and laggy UIs. Jetpack Paging 3 solves this by loading data in chunks (pages), fetching more only when needed. It works with Room, Retrofit, and any custom data source.
[ADD IMAGE - Paging flow diagram]
Alt: Diagram showing Paging 3 data flow from data source to UI
2) Why Use Paging 3?
- Asynchronous loading with Kotlin coroutines
- Seamless integration with Flow and LiveData
- Supports network + database caching (RemoteMediator)
- Handles UI states (loading, error, retry) out of the box
Tip: Paging 3 can be combined with Room for offline-first apps.
3) Setting Up Paging 3 in Your Project
First, add dependencies to your build.gradle
:
dependencies {
implementation "androidx.paging:paging-runtime:3.3.0" // For Kotlin
// or
implementation "androidx.paging:paging-runtime-ktx:3.3.0"
}
4) Implementing a PagingSource
A PagingSource
defines how data is loaded page-by-page.
class ArticlePagingSource(
private val api: ArticleApi
) : PagingSource<Int, Article>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Article> {
return try {
val page = params.key ?: 1
val response = api.getArticles(page)
LoadResult.Page(
data = response.articles,
prevKey = if (page == 1) null else page - 1,
nextKey = if (response.articles.isEmpty()) null else page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Int, Article>): Int? {
return state.anchorPosition?.let { anchor ->
state.closestPageToPosition(anchor)?.prevKey?.plus(1)
?: state.closestPageToPosition(anchor)?.nextKey?.minus(1)
}
}
}
5) Integrating with ViewModel & Repository
class ArticleRepository(private val api: ArticleApi) {
fun getArticles(): Pager<Int, Article> {
return Pager(
config = PagingConfig(pageSize = 20),
pagingSourceFactory = { ArticlePagingSource(api) }
)
}
}
class ArticleViewModel(private val repository: ArticleRepository) : ViewModel() {
val articles = repository.getArticles()
.flow
.cachedIn(viewModelScope)
}
6) Displaying Data in RecyclerView
Use PagingDataAdapter
for RecyclerView integration.
class ArticleAdapter : PagingDataAdapter<Article, ArticleViewHolder>(DIFF_CALLBACK) {
override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
getItem(position)?.let { holder.bind(it) }
}
// ...
}
7) Handling Loading & Error States
Paging 3 offers LoadStateAdapter
for displaying loading spinners and retry buttons.
Tip: Always provide a retry mechanism for network errors to improve UX.
8) Best Practices for Performance
- Use cachedIn to retain paging data across configuration changes
- Set prefetchDistance in
PagingConfig
to load data earlier - Combine RemoteMediator for offline + online data sync
9) Common Mistakes to Avoid
- Loading all data at once instead of using paging
- Not handling empty state UI
- Blocking UI thread with heavy operations in bind
10) Conclusion & Further Reading
Jetpack Paging 3 simplifies pagination while maintaining performance and scalability. By following best practices and avoiding common mistakes, you can create smooth, responsive lists in your Android apps.
Further resources:
Appendix
References
- Android Developers Docs
- Kotlin Coroutines Guide
Note: This document is fully compatible with WYSIWYG editors.