Я не уверен, что вы видите, чтобы сделать вывод, что вы выполняете запрос несколько раз, но я могу заверить вас, что это не так.
Перехватчики
OkHttp
работают как цепочка, отсюда и название chain
для класса, который вы получаете в методе перехватчика. Перехватчики запускаются в порядке сложения для запросов и в обратном порядке сложения для ответов. Например, если вы добавите сначала перехватчик журналирования, а затем аутентификацию, вы будете сначала запускать регистратор для запросов, а затем аутентификацию. Это означает, что вы не увидите заголовки аутентификации запроса (или любого другого поля аутентификации), потому что они добавляются после того, как вы зарегистрировали запрос.
Напротив, если вы добавите перехватчик регистрации в конце, вы увидите все, что было добавлено предыдущими перехватчиками.
Давайте рассмотрим общий пример: A->B->C
- это цепочка перехватчиков, которая была добавлена в алфавитном порядке. Это означает, что сначала запускается A
, затем B
, а затем C
для запросов и ответов, сначала запускается C
, затем B
, а затем A
. Когда A
завершен с запросом, он может позвонить chain.proceed
, и он перейдет к запросу на B
. То же самое для B
, когда он хочет «продолжить» запрос в цепочке. Как только все перехватчики выполнены, OkHttp
выполнит запрос один раз и выполнит ответ через все перехватчики в обратном порядке. Другими словами, именно здесь возникает концепция цепочки. Это почти похоже на композицию функций в функциональном программировании.
В конце концов, вы не выполняете запрос несколько раз, если вы звоните chain.proceed(chain.request)
, вы просто передаете его по цепочке и ожидаете ответа.
Вот официальное объяснение , которое будет намного лучше моего.