Почему request B зависит от request A
Что проверяют
Видите ли вы разницу между «запросы идут подряд» и «один нужен другому», и что делаете, когда первый упал. Зависимость это свойство данных, а не сети, и от того, правильно ли вы её опознали, зависит время открытия экрана.
Как отвечать
B зависит от A, если из ответа A берётся хоть одно значение для B: идентификатор в путь, токен в заголовок, курсор для следующей страницы. Во всех остальных случаях запросы независимы и должны идти параллельно.
val user = api.getUser() // A
val orders = api.getOrders(user.id) // B ждёт A, иначе нечего подставитьcoroutineScope {
val profile = async { api.getProfile() }
val feed = async { api.getFeed() }
render(profile.await(), feed.await())
}Дальше стоит проговорить последствия зависимости:
- ошибка A отменяет B целиком, повтор вешается на A, а не на хвост цепочки;
- structured concurrency: падение внутри
coroutineScopeотменяет соседей, отдельныйSupervisorJobнужен, только если часть экрана может жить без данных; - цепочка живёт в репозитории, а не в презентере и тем более не в колбэке подписки;
- единый источник правды: UI читает
Flowиз базы, сеть только пополняет её, поэтому повторный вход на экран не запускает цепочку заново.
Где спотыкаются
Называют зависимыми запросы, которые просто написаны один под другим. Два последовательных await на независимых вызовах складывают задержки, и экран открывается вдвое дольше без единой причины.
Собирают цепочку на уровне UI: подписались на результат, внутри обработчика дёрнули второй вызов. После поворота экрана или возврата с фона всё это стартует повторно, и B уходит дважды, иногда с идентификатором прошлого пользователя.
Не продумывают отмену. Пользователь ушёл с экрана, A уже вернулся, B улетел в сеть и пишет результат в мёртвую вьюмодель. Область корутины должна умирать вместе с экраном, тогда вопрос снимается сам.