Summary

Review a summary of the course.

We'll cover the following...

There is still so much more to say about Kotlin coroutines, but we’ve covered the essentials. Now it’s your turn to start using this knowledge in practice and deepen your understanding.

In summary, here are the essential use cases and some reflections on good style. First, if we introduce coroutines into our code, it’s best to use them from the bottom to the top of our application. We should avoid mixing suspending functions with blocking functions in other concurrency styles, like callbacks or explicit thread starting. The easiest way to achieve this is by using libraries with built-in support for suspending functions.

Press + to interact
// Retrofit
class GithubApi {
@GET("orgs/{organization}/repos?per_page=100")
suspend fun getOrganizationRepos(
@Path("organization") organization: String
): List<Repo>
}
// Room
@Dao
interface LocationDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertLocation(location: Location)
@Query("DELETE FROM location_table")
suspend fun deleteLocations()
@Query("SELECT * FROM location_table ORDER BY time")
fun observeLocations(): Flow<List<Location>>
}

If we can’t avoid calling a blocking function, wrap it with withContext and set a proper dispatcher (either Dispatchers.IO or a custom dispatcher built using Dispatchers.IO and limitedParallelism).

Note: For details, see the “ ...

Press + to interact
class DiscUserRepository(
private val discReader: DiscReader
) : UserRepository {
private val dispatcher = Dispatchers.IO
.limitedParallelism(5)
override suspend fun getUser(): UserData =
withContext(dispatcher) {
discReader.read<UserData>("userName")
}
}

If we need to use a ...