MyFamilyTracker
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Loading a thousand-item list all at once is how apps run out of memory and feel sluggish. Paging 3 loads data in chunks as the user scrolls. Here's how it fits together with Compose, Room, and a network source.
On this page
The naive way to show a long list is to load everything into memory and hand it to the UI. It works for fifty items and falls apart at five thousand — memory balloons, the initial load drags, and scrolling stutters. Paging 3 is Jetpack's answer: it loads data in pages as the user scrolls, keeps memory bounded, and handles the fiddly states — loading, error, retry, end-of-list — that you'd otherwise hand-roll badly. It has a few moving parts, but they click together cleanly.
Paging 3 centers on three things. A
PagingSourcePagerPagingDataval items: Flow<PagingData<Item>> = Pager(
config = PagingConfig(pageSize = 20),
) {
ItemPagingSource(api)
}.flow.cachedIn(viewModelScope)The
cachedIn(viewModelScope)On the UI side, Paging has first-class Compose support. You collect the paging data and drive a
LazyColumnval items = viewModel.items.collectAsLazyPagingItems()
LazyColumn {
items(items.itemCount) { index ->
items[index]?.let { ItemRow(it) }
}
}As the user scrolls near the end of what's loaded, Paging requests the next page automatically. You don't write scroll listeners or threshold math — it watches access patterns and prefetches for you.
The part people skip and regret is load-state handling. A paged list has more states than a simple one: the initial load, appending the next page, refreshing, and the error variants of each. Paging exposes all of them through
loadStatewhenFor an offline-capable app, the strong pattern is paging from the local database and using a
RemoteMediatorA closing caution in the spirit of keeping things simple: Paging 3 is the right tool for genuinely large or unbounded lists, and it's overkill for a list of twenty items you already have in memory. The configuration and load-state handling are real overhead, and applying them to a short, fixed list is complexity with no payoff. I reach for Paging when the data is large enough that loading it all at once is a genuine memory or performance problem, and I use a plain
LazyColumnThe reason Paging 3 has more moving parts than a plain list is that it's solving genuinely harder problems — bounded memory, prefetching, the full matrix of load and error states, and optionally an offline cache — that you'd otherwise have to solve yourself, badly. When the data is large enough to need those solutions, having them handed to you in a coherent library is a real gift, and the setup cost pays for itself the first time the network fails mid-scroll and your list degrades gracefully instead of breaking. When the data is small, none of those problems exist, and the library is answering questions nobody asked. So the whole decision reduces to one honest look at your data's scale, which is exactly the kind of judgment that keeps a codebase free of complexity it doesn't need.
PagingSourcePagerPagingDatacachedIncollectAsLazyPagingItemsLazyColumnRemoteMediatorLazyColumnSudarshan Chaudhari
AI Systems Builder / Product Engineer
Bangkok, Thailand
Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.
Related Posts
Related Apps
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Building something? Available for Android dev and QA consulting.
Work with meComments — powered by Giscus
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
ReadPrivate dream journal — structured entry capture, pattern tagging, and optional Claude-powered insight generation. All data stays on-device by default.
ReadWorkout tracker — exercise logging with set/rep/weight history, goal progression, and local Room DB persistence. No account, no cloud sync required.
Read