article banner

Exercise: All users flow

You fetch users from an API that uses pagination. You want to expose a flow that emits all users. Implement a getAllUsers function that returns a flow of all users. Use a fetchUsers function to fetch users from the API. You can assume that the fetchUsers function is already implemented. It takes a page number as a parameter and returns a list of users from that page. If there are no more pages, it returns an empty list. You should fetch pages on demand.

Starting code:

class AllUsers(private val repository: UserRepository) { fun getAllUsers(): Flow<User> = TODO() } interface UserRepository { fun fetchUsers(pageNumber: Int): List<User> }

This problem can either be solved in the below playground or you can clone kotlin-exercises project and solve it locally. In the project, you can find code template for this exercise in coroutines/flow/AllUsers.kt. You can find there starting code and unit tests.

Once you are done with the exercise, you can check your solution here.

Playground

import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.count import kotlinx.coroutines.flow.flow import kotlinx.coroutines.test.runTest import org.junit.Test import kotlin.test.assertEquals class AllUsers(private val repository: UserRepository) { fun getAllUsers(): Flow<User> = TODO() } interface UserRepository { fun fetchUsers(pageNumber: Int): List<User> } data class User(val name: String) internal class AllUsersTests { @Test fun test() = runTest { val size = 10_000 val pageSize = 10 val repo = object : UserRepository { val users = List(size) { User("User$it") } var timesUsed = 0 override fun fetchUsers(pageNumber: Int): List<User> = users.drop(pageSize * pageNumber) .take(pageSize) .also { timesUsed++ } } val service = AllUsers(repo) val s = service.getAllUsers() assertEquals(size, s.count()) assertEquals(size / pageSize + 1, repo.timesUsed) } }