Сравнение сетевых библиотек Android: OkHTTP, Retrofit и Volley [закрыто]


579

Вопрос из двух частей от разработчика iOS, изучающего Android, работающего над проектом Android, который будет выполнять различные запросы от JSON к изображению для потоковой загрузки аудио и видео:

  1. На iOS я широко использовал проект AFNetworking . Есть ли эквивалентная библиотека для Android?

  2. Я читал о OkHTTP и Retrofit by Square, а также о Volley, но пока не имею опыта разработки с ними. Я надеюсь, что кто-то может предоставить некоторые конкретные примеры лучших вариантов использования для каждого. Из того, что я прочитал, кажется, что OkHTTP - самый надежный из трех, и может удовлетворить требования этого проекта (упомянутые выше).


3
Если вы используете внутреннюю реализацию HttpUrlConnection, вы должны учитывать, что HttpUrlConnection использует автоматические повторные попытки POST-запросов. Это причинило мне много вреда. Для получения дополнительной информации читайте здесь: stackoverflow.com/a/37675253/2061089
Оли

1
если кому-то нужен список всех сетевых библиотек, вы можете найти его в моем блоге androidredman.wordpress.com/2017/06/26/…
Манохар Редди

Volley может работать с устаревшими Apache, HttpUrlConnection, Apache-4 или OkHttp. Где Retrofit действительно работает только OkHttp. Модифицировать намного проще в настройке.
битсабхи

Ответы:


647

Я надеюсь, что кто-то может предоставить некоторые конкретные примеры лучших вариантов использования для каждого.

Используйте Retrofit, если вы общаетесь с веб-сервисом. Используйте одноранговую библиотеку Picasso, если вы загружаете изображения. Используйте OkHTTP, если вам нужно выполнить операции HTTP, которые находятся за пределами Retrofit / Picasso.

Залп грубо конкурирует с Retrofit + Picasso. С другой стороны, это одна библиотека. С минусовой стороны, это одна недокументированная, неподдерживаемая библиотека «бросьте код через стену и сделайте презентацию ввода-вывода на нем».

РЕДАКТИРОВАТЬ - Volley теперь официально поддерживается Google. Пожалуйста, обратитесь к руководству Google для разработчиков

Из того, что я прочитал, кажется, что OkHTTP является самым надежным из 3

Дооснащение использует OkHTTP автоматически, если доступно. Есть Гист от Джейка Уортона, который связывает залп с OkHTTP.

и может справиться с требованиями этого проекта (упомянутых выше).

Вероятно, вы не будете использовать ни один из них для «потоковой загрузки аудио и видео», согласно общепринятому определению «потоковая передача». Вместо этого медиа-инфраструктура Android будет обрабатывать эти HTTP-запросы для вас.

При этом, если вы собираетесь попытаться сделать свою собственную потоковую передачу на основе HTTP, OkHTTP должен обработать этот сценарий; Я не помню, насколько хорошо Волли справился бы с этим сценарием. Ни Retrofit, ни Пикассо не предназначены для этого.


4
Спасибо @CommonsWare за краткий ответ и заметку о недокументированном Стиле Волли (такое впечатление сложилось, особенно в сравнении с другими проектами). Определенно помогает мне сорваться с земли.
Алфи Хансен

18
Еще один отличный ответ от @CommonsWare. Может кто-нибудь выяснить, как RoboSpice вписывается во все это?
user1923613

3
@ user1923613 github.com/octo-online/robospice Если вы используете volley для сетевых вызовов, то вам не нужно использовать robospice! volley выполняет многие действия, которые Robospice делает для сетевых вызовов, Robospice поддерживает REST из коробки (используя Spring Android или Google Http Client или Retrofit). Если вам нужна быстрая сеть и загрузка изображений с надежным сетевым клиентом, вы можете пойти на залп! но вы можете заменить обычную асинхронную задачу Android, которую используете Robospice, для повышения производительности и избежания утечек памяти!
LOG_TAG

4
@frostymarvelous: я считаю, что недокументированное и неподдерживаемое оправдание более чем достаточно. Не то чтобы у Google не было системы для более формальной обработки таких вещей, как эта (например, библиотека поддержки Android). За два года, прошедшие с этого ответа, с другой стороны, существует некоторая поддержка сообщества, включая некоторую неофициальную упаковку кода в артефакт.
CommonsWare

4
@AbhinavVutukuri: Вы комментируете ответ более двух лет назад. На тот момент документации не было.
CommonsWare

361

Глядя на перспективу залпа, вот некоторые преимущества для вашего требования:

Volley, с одной стороны, полностью сосредоточен на обработке отдельных небольших HTTP-запросов. Так что если у вашей обработки HTTP-запроса есть свои причуды, у Volley, вероятно, есть ловушка для вас. Если, с другой стороны, у вас есть странность в обработке изображений, единственная реальная ловушка - это ImageCache . «Это не ничего, но это не так много!» но у него есть и другие преимущества: например, после того, как вы определили свои запросы, их использование внутри фрагмента или действия безболезненно в отличие от параллельных AsyncTasks.

Плюсы и минусы залпа:

Так что хорошего в Волей?

  • Сетевая часть не только для изображений. Залп предназначен для того, чтобы стать неотъемлемой частью вашего бэкенда. Для нового проекта, основанного на простом сервисе REST, это может быть большой победой.

  • NetworkImageView более агрессивен в отношении очистки запросов, чем Picasso, и более консервативен в своих шаблонах использования GC. NetworkImageView полагается исключительно на сильные ссылки на память и очищает все данные запроса, как только будет сделан новый запрос для ImageView, или как только этот ImageView переместится за пределы экрана.

  • Представление. Этот пост не будет оценивать это утверждение, но они явно позаботились о том, чтобы быть разумными в своих моделях использования памяти. Volley также пытается пакетировать обратные вызовы в основной поток, чтобы уменьшить переключение контекста.

  • У Волли, видимо, тоже есть будущее. Проверьте RequestFuture, если вы заинтересованы.

  • Если вы имеете дело со сжатыми изображениями с высоким разрешением, Volley - единственное решение, которое работает хорошо.

  • Залп может быть использован с Okhttp (новая версия Okhttp поддерживает NIO для лучшей производительности)

  • Залп хорошо играет с жизненным циклом деятельности.

Проблемы с Volley:
поскольку Volley является новым, кое-что еще не поддерживается, но оно исправлено.

  1. Составные запросы (решение: https://github.com/vinaysshenoy/enhanced-volley )

  2. Код состояния 201 воспринимается как ошибка, Код состояния от 200 до 207 теперь являются успешными ответами. (Исправлено: https://github.com/Vinayrraj/CustomVolley )

    Обновление: в последней версии Google залпа, то 2XX коды статуса ошибка является фиксированной теперь благодаря Ficus Киркпатрик!

  3. это менее документировано, но многие люди поддерживают залп в github, java-подобную документацию можно найти здесь . На веб-сайте разработчика Android вы можете найти руководство по передаче сетевых данных с помощью Volley . И залп исходный код можно найти в Google Git

  4. Чтобы решить / изменить Политику перенаправления Volley Framework, используйте Volley с OkHTTP (CommonsWare, упомянутый выше)

Также вы можете прочитать это Сравнение загрузки изображения залпа с Пикассо

Модифицированные:

Это выпущено Square , Это предлагает очень простой в использовании REST API (Обновление: Voila! С поддержкой NIO)

Плюсы модернизации:

  • По сравнению с Volley, REST API-код Retrofit является кратким, предоставляет отличную документацию по API и имеет хорошую поддержку в сообществах! Это очень легко добавить в проекты.

  • Мы можем использовать его с любой библиотекой сериализации, с обработкой ошибок.

Обновление: - В Retrofit 2.0.0-beta2 есть много очень хороших изменений

  • Версия 1.6 Retrofit с OkHttp 2.0 теперь зависит от Okio для поддержки java.io и java.nio, что упрощает доступ, хранение и обработку ваших данных, используя ByteString и Buffer, чтобы делать некоторые умные вещи для экономии ресурсов процессора и памяти. (К вашему сведению: это напоминает мне о библиотеке OIN Koush с поддержкой NIO!) Мы можем использовать Retrofit вместе с RxJava для объединения и цепочки вызовов REST, используя rxObservables, чтобы избежать уродливых цепочек обратных вызовов (чтобы избежать ада обратного вызова !!) .

Минусы Retrofit для версии 1.6:

  • Функциональность обработки ошибок, связанных с памятью, не очень хорошая (в более старых версиях Retrofit / OkHttp), не уверен, что она улучшена с помощью Okio с поддержкой Java NIO.

  • Минимальная помощь при многопоточности может привести к обратному вызову ада, если мы используем это ненадлежащим образом.

(Все вышеперечисленные минусы были решены в новой версии Retrofit 2.0 beta)

================================================== ======================

Обновить:

Сравнение производительности Android Async и Volley против Retrofit (миллисекунды, чем меньше значение, тем лучше):

Тестирование производительности Android Async против Volley и Retrofit

(К сведению выше, информация о тестах Retrofit улучшится с поддержкой Java NIO, потому что новая версия OKhttp зависит от библиотеки NIO Okio)

Во всех трех тестах с различными повторениями (1 - 25 раз) Volley был где-то на 50-75% быстрее. Дооснащение происходило с впечатляющей скоростью от 50% до 90% быстрее, чем задачи AsyncTasks, достигая одной и той же конечной точки такое же количество раз. В тестовом наборе Dashboard это привело к загрузке / анализу данных на несколько секунд быстрее. Это огромная разница в реальном мире. Чтобы сделать тесты честными, время для AsyncTasks / Volley включало анализ JSON, так как Retrofit делает это автоматически.

RetroFit Побед в тесте производительности!

В конце концов, мы решили использовать Retrofit для нашего приложения. Это не только смехотворно быстро, но и вполне соответствует нашей существующей архитектуре. Мы смогли создать родительский интерфейс обратного вызова, который автоматически выполняет обработку ошибок, кэширование и разбиение на страницы без каких-либо усилий для наших API. Чтобы объединить Retrofit, нам пришлось переименовать наши переменные, чтобы сделать наши модели совместимыми с GSON, написать несколько простых интерфейсов, удалить функции из старого API и изменить наши фрагменты, чтобы они не использовали AsyncTasks. Теперь, когда у нас есть несколько полностью преобразованных фрагментов, это довольно безболезненно. Были некоторые проблемы с ростом и проблемы, которые нам пришлось преодолеть, но в целом все прошло гладко. В начале мы столкнулись с несколькими техническими проблемами / ошибками, но у Square есть фантастическое сообщество Google+, которое помогло нам в этом.

Когда использовать залп ?!

Мы можем использовать Volley, когда нам нужно загрузить изображения, а также использовать API-интерфейсы REST! ​​Система очередей сетевых вызовов необходима для выполнения множества запросов одновременно! также Volley имеет лучшую обработку ошибок, связанных с памятью, чем Retrofit!

OkHttp можно использовать с Volley, Retrofit по умолчанию использует OkHttp ! Имеет поддержку SPDY , пул соединений, кеширование дисков, прозрачное сжатие! Недавно он получил некоторую поддержку Java NIO с библиотекой Okio .

Источник, кредит: залп против модернизации г-н Джош Рюш

Примечание: о потоковой передаче зависит от того, какой тип потоковой передачи вы хотите, например, RTSP / RTCP.


@ Jan1337z +1 за информацию! Я обновил это! android.googlesource.com/platform/frameworks/volley
LOG_TAG

4
@LOG_TAG было бы интересно протестировать RoboSpice в вашем примере. Мы даже предлагаем модуль Retrofit, поэтому я считаю, что это потребует очень мало изменений. Источник доступен где-нибудь? Преимущество RS в том, что он правильно обрабатывает жизненный цикл действия, которое выполняет сетевые запросы, и мы также обеспечиваем прозрачное кэширование, я думаю, что издержки будут небольшими по сравнению с чистым запросом на модернизацию.
Сниколас

@Snicolas Я получил результаты тестов в блоге Джоша Рюша, вы можете увидеть конверсию между Фикусом Киркпатриком (основателем Volley) и Джошем Рюшем! Он еще не поделился тестовым проектом нигде! К вашему сведению, я только начал изучать ваш RoboSpice с образцом дооснащения, столкнувшись с этой проблемой уведомления :)
LOG_TAG

3
Привет! Что касается Multipart Requests с Volley, я думаю, что мы можем использовать MultipartEntityBuilderв httpmimeбиблиотеке с ним.
БНК

2
Кто-нибудь еще проверял эти критерии? Поскольку http-библиотека apache устарела в M (и я использовал ее для многокомпонентного компоновщика), я решил перенести свой сетевой код в Retrofit. Сначала я изменил один из вызовов GET, чтобы получить кучу объектов с сервера. Я рассчитал Retrofit против AsyncTask (с моим собственным анализом JSON). Производительность была очень близкой, а не трехкратное улучшение, как показано в столбце «Одно обсуждение» таблицы. Конечно, полученный код намного чище, и мне не нужно было писать свой собственный анализатор JSON, но для одного запроса GET улучшения не было.
Гэри Кипнис

44

RoboSpice Vs. залп

Из https://groups.google.com/forum/#!topic/robospice/QwVCfY_glOQ

  • RoboSpice (RS) основан на сервисах и более уважает философию Android, чем Volley. Volley основан на потоках, и это не тот способ, которым фоновая обработка должна выполняться в Android. В конечном счете, вы можете найти обе библиотеки и найти их довольно схожими, но наш способ выполнения фоновой обработки в большей степени ориентирован на Android, что позволяет нам, например, сказать пользователям, что RS на самом деле делает что-то в фоновом режиме, что было бы трудно для залпа (на самом деле это не так).
  • RoboSpice и volley предлагают приятные функции, такие как расстановка приоритетов, политика повторных попыток, отмена запроса. Но RS предлагает больше: более продвинутое кеширование, и это большое, с управлением кешем, агрегацией запросов, дополнительными функциями, такими как повторное подключение к ожидающему запросу, работа с истечением срока действия кеша без использования заголовков сервера и т. Д.
  • RoboSpice делает больше вне UI Thread: volley десериализует ваши POJO в основном потоке, что, на мой взгляд, ужасно. С RS ваше приложение будет более отзывчивым.
  • С точки зрения скорости нам определенно нужны метрики. Сейчас RS стал очень быстрым, но мы все еще не можем это представить. Залп теоретически должен быть немного быстрее, но RS теперь массивно параллелен ... кто знает?
  • RoboSpice предлагает большой диапазон совместимости с расширениями. Вы можете использовать его с okhttp, retrofit, ormlite (бета), jackson, jackson2, gson, xml сериализатором, клиентом google http, spring android ... Довольно много. Залп может использоваться с ok http и использует gson. это оно.
  • Залп предлагает больше UI сахара, чем RS. Volley предоставляет NetworkImageView, RS предоставляет адаптер списков специй. С точки зрения возможностей это не так далеко, но я считаю, что Волли более продвинут в этой теме.
  • Более 200 ошибок было исправлено в RoboSpice с момента его первоначального выпуска. Это довольно прочный и интенсивно используется в производстве. Залп менее зрелый, но его пользовательская база должна быстро расти (эффект Google).
  • RoboSpice доступен на Maven Central. Залп трудно найти;)

Robospice использует службы Android для вызова REST, мы можем использовать Robospice с Retrofit, чтобы минимизировать усилия по разбору gson, точно так же, как мы можем использовать Volley (на основе протектора) с Robospice? (не уверен, что это правильный вопрос.) Я просто ищу залп с обслуживанием!
LOG_TAG

1
Залп с обслуживанием в основном РС. Или, в хронологическом порядке, Volley является RS без обслуживания и некоторые другие функции отсутствуют. И да, вы можете использовать Retrofit с RS, а также даже добавить okhttp, если хотите.
Snicolas

7
Почему залп трудно найти? compile 'com.mcxiaoke.volley:library:1.0.+'
Роб

1
@Rob было время, когда клон Максиоке не был доступен. Вы должны были вручную включить залп в ваше приложение.
морозный

msgstr "залп десериализует ваши POJO в главном потоке". Вы можете получить возвращенные данные JSON и десериализовать их самостоятельно в отдельном потоке, если это является проблемой.
AndroidDev

20

AFNetworking для Android:

Быстрый Android Networking является здесь

Fast Android Networking Library поддерживает все типы запросов HTTP / HTTPS, такие как GET, POST, DELETE, HEAD, PUT, PATCH

Fast Android Networking Library поддерживает загрузку файлов любого типа

Fast Android Networking Library поддерживает загрузку файлов любого типа (поддерживает многочастную загрузку)

Fast Android Networking Library поддерживает отмену запроса

Fast Android Networking Library поддерживает установку приоритета для любого запроса (НИЗКИЙ, СРЕДНИЙ, ВЫСОКИЙ, НЕМЕДЛЕННЫЙ)

Быстрая сетевая библиотека Android поддерживает RxJava

Поскольку он использует OkHttp в качестве сетевого уровня, он поддерживает:

Fast Android Networking Library поддерживает HTTP / 2, позволяет всем запросам к одному хосту совместно использовать сокет

Fast Android Networking Library использует пул соединений, что уменьшает задержку запросов (если HTTP / 2 недоступен)

Прозрачный GZIP сжимает размеры загрузки

Fast Android Networking Library поддерживает кэширование ответов, что полностью исключает повторные запросы в сети

Спасибо: библиотека создана мной


1
Вы заявляете, что ваша библиотека поддерживает HTTP / 2, но не говорите, существует ли требование API для поддержки HTTP / 2. Насколько я понимаю, уровень API Android ниже 5.0 не имеет подходящих методов шифрования SSL для поддержки HTTP / 2. Не стучите, просто пытайтесь полностью оценить предложенное решение.
DoctorD

@AmitShekhar: я просто хотел узнать, какой из них лучше всего подходит для API-вызовов в Android. Я использую сетевую библиотеку Android, так что же здорово использовать Retrofit, Volley или Android Networking?
Парт Бхайани

@Amit Shekhar Насколько эффективна быстрая Android-сеть для многоэтапной загрузки изображений, особенно когда речь идет о сценариях с низким интернетом?
user3135923

18

Асинхронный HTTP-клиент loopj vs. Volley

Специфика моего проекта - маленькие HTTP-запросы REST, каждые 1-5 минут.

Я давно использовал асинхронный HTTP-клиент (1.4.1). Производительность выше, чем при использовании ванильного Apache httpClient или HTTP-URL-соединения. Как бы то ни было, новая версия библиотеки не работает для меня: библиотека исключений исключает цепочку обратных вызовов.

Чтение всех ответов побудило меня попробовать что-то новое. Я выбрал библиотеку HTTP залпов.

После его использования в течение некоторого времени, даже без тестов, я ясно вижу, что время отклика уменьшилось до 1,5x, 2x Volley.

Может быть, Retrofit лучше, чем асинхронный HTTP-клиент? Мне нужно попробовать это. Но я уверен, что залп не для меня.


Любой анализ о Retrofit Vs AsyncHttpClient ??? Пожалуйста, напишите, если да @Sergey
IshRoid


Я использую AsyncHttpClient в течение нескольких лет. Плохая часть заключается в том, что репозиторий github составляет 2 года без коммита.
Витор Хьюго Швааб

Его больше не актуально, асинхронный http слишком стар. Подумайте, чтобы перейти на другую библиотеку. Залп также стал очень хорошим выбором.
Сергей Вакуленко

Сергей, @IshRoid Я все еще ищу ответ на ваш вопрос. Я использую AsyncHttpClient, если я буду использовать что-то еще, например, RxJava Retrofit или что-то еще ... Пожалуйста, дайте мне знать ... с нетерпением жду ответа
Deep Dave

11

Просто чтобы добавить немного к обсуждению из моего опыта работы с Volley:

  1. Volley не обрабатывает потоковые загрузки или загрузки в любом смысле. То есть все тело запроса должно находиться в памяти, и вы не можете использовать OutputStreamдля записи тела запроса в базовый сокет, а также не можете использовать InputStreamдля чтения тела ответа, как это HttpURLConnectionделает базовый . Так что Volley - плохой выбор для загрузки или скачивания больших файлов. Ваши запросы и ответы должны быть небольшими. Это одно из самых больших ограничений волейбола, с которым я лично столкнулся. Для чего бы то ни было, OkHttp имеет интерфейсы для работы с потоками.

  2. Отсутствие официальной документации раздражает, хотя я смог обойти это, прочитав исходный код, за которым довольно легко следить. Что более неприятно, так это то, что, насколько я могу судить, у Volley нет официальных версий релизов и нет артефактов Maven или Gradle, и поэтому управление ими как зависимостью становится большей головной болью, чем, скажем, любая из библиотек, выпущенных Square , Вы просто клонируете репо, строите банку, и вы сами по себе. Ищете исправление ошибки? Принеси и надеюсь, что это там. Вы могли бы также получить некоторые другие вещи; это не будет задокументировано. На мой взгляд, это фактически означает, что Volley является неподдерживаемой сторонней библиотекой, хотя база кода достаточно активна. Пусть покупатель будет бдителен.

  3. Как бы то ни было, привязка Content-Type к типу class / request (JsonObjectRequest, ImageRequest и т. Д.) Выглядит довольно неудобно и немного снижает гибкость вызывающего кода, поскольку вы привязаны к существующей иерархии типов запросов Volley. Мне нравится простота установки Content-Type в качестве заголовка, как и любого другого (кстати, не делайте этого с Volley, у вас получится два заголовка Content-Type!). Это только мое личное мнение, и это можно обойти.

Это не значит, что у Volley нет некоторых полезных функций. Это конечно делает. Легко настраиваемые политики повторов, прозрачное кэширование, API отмены и поддержка планирования запросов и одновременных подключений - это отличные возможности. Просто знайте, что он не предназначен для всех случаев использования HTTP (см. Пункт 1 выше), и что есть некоторые головные боли, связанные с использованием Volley для промышленного использования в вашем приложении (пункт 2).


Полная загрузка памяти - это то, что я медленно убиваю. Слава богу, кто-то еще упомянул об этом.
TheSunny

Библиотека также может сделать защитную копию вашего тела запроса, поэтому потребление памяти для больших запросов может быть вдвое больше, чем вы могли бы ожидать.
Джефф

9

Недавно я нашел библиотеку под названием ion, которая приносит немного больше информации.

ion имеет встроенную поддержку загрузки изображений, интегрированную с ImageView, JSON (с помощью GSON), файлы и очень удобную поддержку потоков в пользовательском интерфейсе.

Я использую его в новом проекте, и пока результаты были хорошими. Его использование намного проще, чем Volley или Retrofit.


2
Ион против модернизации, какой из них вы бы порекомендовали?
Sreekanth Karumanaghat,

Дооснащение лучше, чем ион
Раджеш Кости

4

В дополнение к принятому ответу и тому, что LOG_TAG сказал .... для того, чтобы Volley проанализировал ваши данные в фоновом потоке, вы должны создать подкласс, так Request<YourClassName>как onResponseметод вызывается в основном потоке, а синтаксический анализ в основном потоке может вызвать задержку пользовательского интерфейса, если ваш ответ большой. Читайте здесь о том, как это сделать.


1
правильно ... залп анализирует ответ в главном потоке, который вызывает задержку при очень большом отклике.
Гопал Сингх Сирви

3

Модернизация 1.9.0 против RoboSpice

Я использую оба в моем приложении.

Robospice работает быстрее, чем Retrofit всякий раз, когда я анализирую вложенный класс JSON. Потому что Spice Manger сделает все за вас. В Retrofit вам нужно создать GsonConverter и десериализовать его.

Я создал два фрагмента в одном и том же упражнении и позвонил в одно и то же время с двумя одинаковыми типами URL.

09-23 20:12:32.830  16002-16002/com.urbanpro.seeker E/RETROFIT   RestAdapter Init
09-23 20:12:32.833  16002-16002/com.urbanpro.seeker E/RETROFIT calling the method
09-23 20:12:32.837  16002-16002/com.urbanpro.seeker E/ROBOSPICE initialzig spice manager
09-23 20:12:32.860  16002-16002/com.urbanpro.seeker E/ROBOSPICE Executing the method
09-23 20:12:33.537  16002-16002/com.urbanpro.seeker E/ROBOSPICE on SUcceess
09-23 20:12:33.553  16002-16002/com.urbanpro.seeker E/ROBOSPICE gettting the all contents
09-23 20:12:33.601  16002-21819/com.urbanpro.seeker E/RETROFIT deseriazation starts
09-23 20:12:33.603  16002-21819/com.urbanpro.seeker E/RETROFIT deseriazation ends

2

И еще один вариант: https://github.com/apptik/jus

  • Он модульный, как Volley, но более расширенный и документация улучшается, поддерживая различные стеки HTTP и конвертеры из коробки
  • Он имеет модуль для генерации сопоставлений интерфейса API сервера, таких как Retrofit
  • Он также имеет поддержку JavaRx

И многие другие полезные функции, такие как маркеры, трансформаторы и т. Д.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.