The easy way to handle the exception is by waiting on the deferred using join() instead of await(). This way, the exception will not be propagated when waiting. The updated code looks like this:
private fun asyncLoadNews() = launch {
val requests = mutableListOf<Deferred<List<String>>>()
feeds.mapTo(requests) {
asyncFetchHeadlines(it, dispatcher)
}
requests.forEach {
it.join()
}
...
}
Now if you run the application, you will see that it still crashes. This is happening because even though we are not propagating the exception when waiting for deferred, we are propagating the exception when reading from it. Calling getCompleted() in a deferred that was cancelled—in this case because of an exception—will throw the exception.
So we need to also update the code so that getCompleted() is called only when deferred didn't fail:
val headlines = requests
.filter { !it.isCancelled }
.flatMap { it.getCompleted() }
Now, running the application will not crash when an invalid feed is added to the list. It will also handle the device not having connectivity without crashing: