In this short demo, you’ll see how to handle errors in flows.
Open CategoryViewModel.kt and update moviesForCategory() like this:
@OptIn(ExperimentalCoroutinesApi::class)
private fun moviesForCategory(categoryId: String): Flow<List<MovieViewState>> =
movieRepository.categories()
.filter { it.id == categoryId }
.flatMapLatest { movieCategory -> movieRepository.fetchMoviesForCategory(movieCategory.name) }
.map { movies ->
movies.map { movie ->
val imageRes = movieRepository.fetchMovieImage(movieId = movie.id)
MovieViewState(movie.id, movie.title, "", imageRes)
}
}
.catch { throwable -> // HERE
Log.e("CategoryViewModel", "Error happened", throwable)
emit(emptyList())
}
You added the catch operator to the flow. This operator catches any exception that occurs in the upstream flow and
performs a specific action. In this case, you log the error and emit an empty list.
To test this, throw an exception in fetchMoviesForCategory() in MovieRepository.kt:
fun fetchMoviesForCategory(categoryName: String): Flow<List<Movie>> = flow {
if (categoryName == "Action") { // HERE
throw RuntimeException("Error fetching Action movies")
}
val movies = movieService.fetchMoviesForCategory(categoryName)
emit(movies)
}
Run the app now, and navigate to the Action category. You’ll see that the error is caught, and an empty list is emitted. If you try to navigate to another category, you’ll see the movies for that category.
Before continuing, make sure to remove the exception from fetchMoviesForCategory() in MovieRepository.kt.
This ends this demo. In the next lesson, you’ll learn about flow cancellations.