Cursor-Based Pagination with Infinite Scroll in Compose
Cursor-based pagination is efficient for large datasets. Implement infinite scroll by loading more items as the user scrolls.
Data Model
data class PaginatedResponse<T>(
val data: List<T>,
val nextCursor: String? = null,
val hasMore: Boolean = false
)
data class Post(
val id: String,
val title: String,
val content: String,
val timestamp: Long
)
Repository with Pagination
class PostRepository(private val api: PostApi) {
suspend fun getPosts(cursor: String? = null): PaginatedResponse<Post> {
return api.fetchPosts(cursor = cursor)
}
}
ViewModel State Management
class PostViewModel(private val repository: PostRepository) : ViewModel() {
private val _posts = MutableStateFlow<List<Post>>(emptyList())
val posts: StateFlow<List<Post>> = _posts.asStateFlow()
private val _isLoading = MutableStateFlow(false)
val isLoading: StateFlow<Boolean> = _isLoading.asStateFlow()
private var nextCursor: String? = null
fun loadMore() {
viewModelScope.launch {
_isLoading.value = true
val response = repository.getPosts(nextCursor)
_posts.value += response.data
nextCursor = response.nextCursor
_isLoading.value = false
}
}
}
Infinite Scroll Compose
@Composable
fun InfinitePostList(viewModel: PostViewModel) {
val posts by viewModel.posts.collectAsState()
val isLoading by viewModel.isLoading.collectAsState()
val listState = rememberLazyListState()
LaunchedEffect(listState) {
snapshotFlow { listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index }
.collect { lastIndex ->
if (lastIndex != null && lastIndex >= posts.size - 3 && !isLoading) {
viewModel.loadMore()
}
}
}
LazyColumn(state = listState) {
items(posts) { post ->
PostCard(post)
}
if (isLoading) {
item { LoadingIndicator() }
}
}
}
API Request
interface PostApi {
@GET("posts")
suspend fun fetchPosts(
@Query("cursor") cursor: String? = null,
@Query("limit") limit: Int = 20
): PaginatedResponse<Post>
}
Best Practices
- Use cursor tokens for stateless pagination
- Trigger loading when user is 3 items from end
- Avoid duplicate items by tracking cursors
- Handle network errors with retry logic
8 Android app templates on Gumroad
Top comments (0)