Volley — це мережева бібліотека для Android, розроблена компанією Google для ефективного виконання HTTP-запитів і завантаження зображень. Бібліотека автоматично керує пулом потоків, кешує відповіді та пріоритезує запити. За даними Google, 2025, Volley залишається популярним вибором для проєктів, де потрібен швидкий початок без налаштування складних залежностей.
Головне
Volley — це бібліотека для мережевої взаємодії в Android-додатках, представлена компанією Google на конференції I/O 2013. Назва Volley означає «залп» — бібліотека призначена для виконання множини паралельних швидких запитів, характерних для UI-орієнтованих додатків, де важлива швидкість відгуку інтерфейсу.
Volley була створена як вирішення проблем HttpURLConnection та AsyncTask: ручне керування потоками, відсутність кешування, складність пріоритезації запитів та громіздкий код. Google позиціонувала Volley як бібліотеку для операцій типу «fire-and-forget» — невеликих запитів, результат яких одразу відображається в інтерфейсі.
Архітектура Volley включає три основні компоненти: RequestQueue (менеджер черги), CacheDispatcher (потік для кешованих відповідей) та NetworkDispatcher (мережеві потоки). Така архітектура автоматично розподіляє запити: спочатку перевіряється кеш, і тільки за його відсутності виконується мережевий запит. Це скорочує затримку для повторюваних даних на 50–80%.
RequestQueue — центральний клас Volley. До нього додаються об'єкти Request<T>, і черга автоматично розподіляє їх за двома типами потоків: CacheDispatcher (один потік, обробляє запити з можливим кешем) та NetworkDispatcher (кілька потоків, виконують реальні HTTP-запити). За замовчуванням Volley створює 4 мережевих потоки.
При додаванні запиту RequestQueue перевіряє, чи можна його обслужити з кешу. Якщо кеш містить актуальну відповідь, CacheDispatcher повертає її негайно, без мережевого запиту. Якщо кеш застарів або відсутній, запит передається в NetworkDispatcher. Пріоритет запиту (low, normal, high, immediate) визначає порядок обробки всередині черги — запити з високим пріоритетом обробляються раніше звичайних.
Після виконання запиту результат доставляється в основний потік (UI thread) через Handler. Volley автоматично перемикає колбеки onResponse() та onErrorResponse() на головний потік, тому оновлювати інтерфейс можна прямо в колбеку без додаткових перемикань. Це спрощує код та усуває цілий клас помилок із потоками.
Ще одна особливість Volley — автоматична дедуплікація запитів. Якщо до черги додано два однакових GET-запити до одного URL з однаковими параметрами, Volley виконує лише один із них і повертає однакову відповідь обом колбекам. Це особливо корисно для екранів, де кілька компонентів незалежно запитують одні й ті самі дані — наприклад, профіль користувача, який одночасно потрібен і заголовку, і фрагменту з налаштуваннями.
Кожен запит проходить через послідовність кроків: створення Request, додавання в RequestQueue, перевірка кешу (CacheDispatcher), виконання HTTP-запиту (NetworkDispatcher), парсинг відповіді через Response.Listener, доставка результату в UI-потік. При скасуванні запиту (cancel) RequestQueue видаляє його з черги та запобігає виклику колбеків.
Volley також підтримує RetryPolicy, який визначає кількість повторних спроб при збоях. DefaultRetryPolicy за замовчуванням робить одну повторну спробу з таймаутом 2.5 секунди. Для нестабільних з'єднань кількість повторів можна збільшити до 3, а таймаут — до 10 секунд. Кастомний RetryPolicy реалізується через інтерфейс RetryPolicy з методами getCurrentTimeout, getCurrentRetryCount та retry.
Volley надає готові типи запитів для поширених форматів даних. Кожен тип реалізує абстрактний клас Request<T> та визначає спосіб парсингу відповіді. Для кастомних форматів можна створити свій тип, перевизначивши метод parseNetworkResponse.
| Тип запиту | Тип, що повертається | Призначення |
|---|---|---|
| StringRequest | String | Отримання сирої текстової відповіді |
| JsonObjectRequest | JSONObject | Парсинг JSON-об'єкта |
| JsonArrayRequest | JSONArray | Парсинг JSON-масиву |
| ImageRequest | Bitmap | Завантаження та декодування зображення |
| ClearCacheRequest | — | Очищення кешу Volley |
Для роботи з Gson або Kotlinx Serialization можна створити кастомний Request<T>, який у parseNetworkResponse використовує вибраний парсер. Це дозволяє отримувати типізовані об'єкти напряму, минаючи ручний парсинг JSONObject. Такий підхід особливо корисний для проєктів, які вже використовують серіалізацію через Gson або Moshi.
Для надсилання даних Volley підтримує три типи тіла: JSONObject (через JsonObjectRequest з методом POST), Form-encoded (через HashMap<String, String> у конструкторі) та Multipart (через кастомний MultipartRequest). Multipart-запити корисні для завантаження зображень та файлів, але вимагають ручної реалізації, оскільки Volley не має вбудованої підтримки multipart/form-data на відміну від OkHttp або Dio.
Обмеження Volley стають помітними при роботі з великими відповідями. Volley завантажує всю відповідь у пам'ять перед передачею в колбек, що може викликати OutOfMemoryError для JSON-файлів розміром понад 10–20 МБ. Для завантаження великих файлів Volley не підходить — використовуйте DownloadManager або OkHttp з потоковим ResponseBody. Volley також не підтримує докачування перерваних завантажень (Range header) і не працює з потоковими протоколами на кшталт Server-Sent Events або WebSocket у реальному часі.
Розглянемо базовий приклад — StringRequest для отримання даних із сервера. Спочатку створюється RequestQueue через Volley.newRequestQueue(context). Потім формується запит із URL та колбеками на успіх та помилку.
val queue = Volley.newRequestQueue(context)
val request = StringRequest(
Request.Method.GET,
"https://api.github.com/users/octocat",
{ response ->
println("Відповідь: $response")
},
{ error ->
println("Помилка: ${error.message}")
}
)
queue.add(request)
Для JSON-запиту використовується JsonObjectRequest, який автоматично парсить відповідь у JSONObject. Volley підтримує GET та POST запити. Для POST передається JSONObject у тілі запиту.
val jsonBody = JSONObject()
jsonBody.put("name", "New Repo")
jsonBody.put("description", "Created via Volley")
val request = JsonObjectRequest(
Request.Method.POST,
"https://api.github.com/user/repos",
jsonBody,
{ response ->
println("Створено: ${response.getString("id")}")
},
{ println("Помилка: $it") }
)
queue.add(request)
Для скасування запиту використовується метод cancel() або групове скасування за тегом. При скасуванні Volley не викликає ні onResponse, ні onErrorResponse, що запобігає оновленню інтерфейсу після виходу з екрана. Це важливо для запобігання витокам пам'яті в Activity та Fragment.
request.tag = "profile_request"
queue.add(request)
// Скасування при виході з екрана
queue.cancelAll("profile_request")
ImageLoader — це клас-обгортка над RequestQueue, оптимізований для завантаження зображень. Він підтримує memory-кеш (LruCache) та автоматично скасовує запити при перевикористанні ImageView у списках RecyclerView. ImageLoader також масштабує зображення під розмір View, економлячи пам'ять.
NetworkImageView — це кастомний View, який інтегрується з ImageLoader та автоматично керує завантаженням: встановлює placeholder при завантаженні, замінює на помилку при збої та скасовує запит при виході View з екрана. DefaultImageUrlLoader завантажує зображення за URL та зберігає його в LruCache для швидкого повторного відображення.
Для використання ImageLoader достатньо створити екземпляр через ImageLoader(queue, ImageCache), де ImageCache — реалізація інтерфейсу ImageCache з LruCache всередині. NetworkImageView у XML-розмітці зв'язується з ImageLoader через метод setImageUrl(), і все завантаження відбувається повністю автоматично без додаткового коду для обробки placeholder та помилок.
Створення RequestQueue у кожному Activity — часта помилка, що призводить до дублювання потоків та плутанини в кеші. RequestQueue рекомендується створювати один раз в Application або через сінглтон-клас. В іншому випадку кожен екран матиме свій пул потоків, а кеш зберігатиметься окремо для кожної черги.
Ігнорування скасування запитів при повороті екрана. При зміні конфігурації Activity перестворюється, і колбеки старої Activity продовжують висіти в пам'яті. Це призводить до витоку та спроби оновити знищений View. Завжди скасовуйте запити в onStop() через cancelAll() за тегом, специфічним для Activity.
Volley не підтримує HTTP/2 та корутини — це не помилка використання, а архітектурне обмеження. Volley був створений у 2013 році та не підтримує сучасні протоколи та Kotlin-корутини. Для нових проєктів Google рекомендує використовувати Retrofit + OkHttp. Volley підходить тільки для підтримки легасі-проєктів або простих додатків з мінімальними мережевими вимогами.
Часті запитання
Volley застарів для нових проєктів — Google не оновлював бібліотеку з 2017 року. Для сучасних додатків використовуйте Retrofit + OkHttp або Ktor Client. Volley може застосовуватися тільки для підтримки існуючого легасі-коду або в простих навчальних проєктах з мінімальними мережевими завданнями.
Відсутність підтримки сучасних технологій: HTTP/2, Kotlin-корутин, мультиплатформенності та типізованої серіалізації. Volley використовує JSONObject та JSONArray без типів, що призводить до помилок runtime при невідповідності структури JSON очікуванням.
Через ImageLoader та NetworkImageView. ImageLoader використовує LruCache для memory-кешування зображень та автоматично скасовує запити при перевикористанні View. NetworkImageView показує placeholder під час завантаження та замінює його на готове зображення або індикатор помилки.
Технічно так — через обгортку suspendCoroutine { } над колбеками Volley. Але це не дає переваг, оскільки Volley не підтримує скасування за скасуванням корутини та не працює з Dispatchers.IO напряму. Краще використовувати Ktor Client з нативною підтримкою корутин.
Таймаут налаштовується через RetryPolicy. За замовчуванням DefaultRetryPolicy використовує таймаут 2.5 секунди та одну повторну спробу. Змінити параметри: request.retryPolicy = DefaultRetryPolicy(10000, 1, 1.0f) — 10 секунд таймауту, одна спроба.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також