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) определя реда на обработка в опашката — заявките с приоритет high се обработват преди normal.
След изпълнение на заявката резултатът се доставя до главната нишка (UI thread) чрез Handler. Volley автоматично превключва callback-овете onResponse() и onErrorResponse() към главната нишка, така че можете директно да актуализирате интерфейса в callback-а без допълнителни превключвания. Това опростява кода и елиминира цял клас грешки, свързани с нишки.
Друга характеристика на Volley е автоматичното дедуплициране на заявки. Ако две идентични GET заявки към един и същ URL с еднакви параметри бъдат добавени в опашката, Volley изпълнява само една от тях и връща същия отговор и на двата callback-а. Това е особено полезно за екрани, където няколко компонента независимо изискват едни и същи данни — например, потребителски профил, който едновременно е необходим и на заглавната част, и на фрагмента с настройки.
Всяка заявка преминава през поредица от стъпки: създаване на Request, добавяне към RequestQueue, проверка на кеша (CacheDispatcher), изпълнение на HTTP заявка (NetworkDispatcher), парсване на отговор чрез Response.Listener, доставяне на резултата до UI нишката. При отмяна на заявката (cancel) RequestQueue я премахва от опашката и предотвратява извикването на callback-ове.
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 зарежда целия отговор в паметта преди предаването му на callback-а, което може да причини OutOfMemoryError за JSON файлове, по-големи от 10–20 MB. За зареждане на големи файлове Volley не е подходящ — използвайте DownloadManager или OkHttp с потоков ResponseBody. Volley също не поддържа възобновяване на прекъснати изтегляния (Range header) и не работи с потокови протоколи като Server-Sent Events или WebSocket в реално време.
Нека разгледаме основния пример — StringRequest за получаване на данни от сървъра. Първо се създава RequestQueue чрез Volley.newRequestQueue(context). След това се формира заявката с URL и callback-ове за успех и грешка.
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, оптимизиран за зареждане на изображения. Той поддържа паметов кеш (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 или чрез singleton клас. В противен случай всеки екран ще има свой собствен пул от нишки, а кешът ще се съхранява отделно за всяка опашка.
Игнориране на отмяна на заявки при завъртане на екрана. При промяна на конфигурацията Activity се пресъздава и callback-овете на старото Activity остават в паметта. Това води до изтичане и опит за актуализиране на унищожен View. Винаги отменяйте заявките в onStop() чрез cancelAll() с етикет, специфичен за Activity.
Volley не поддържа HTTP/2 и корутини — това не е грешка на използване, а архитектурно ограничение. Volley беше създаден през 2013 г. и не поддържа съвременни протоколи и Kotlin корутини. За нови проекти Google препоръчва Retrofit + OkHttp. Volley е подходящ само за поддръжка на legacy проекти или прости приложения с минимални мрежови изисквания.
Често задавани въпроси
Volley е остарял за нови проекти — Google не е актуализирал библиотеката от 2017 г. За съвременни приложения използвайте Retrofit + OkHttp или Ktor Client. Volley може да се прилага само за поддръжка на съществуващ legacy код или в прости образователни проекти с минимални мрежови задачи.
Липса на поддръжка за съвременни технологии: HTTP/2, Kotlin корутини, мултиплатформеност и типизирана сериализация. Volley използва JSONObject и JSONArray без типове, което води до runtime грешки при несъответствие на структурата на JSON с очакванията.
Чрез ImageLoader и NetworkImageView. ImageLoader използва LruCache за кеширане на изображения в паметта и автоматично отменя заявки при повторно използване на View. NetworkImageView показва placeholder по време на зареждане и го заменя с готовото изображение или индикатор за грешка.
Технически да — чрез обвивка suspendCoroutine { } около callback-овете на Volley. Но това не дава предимства, тъй като Volley не поддържа отмяна чрез отмяна на корутината и не работи директно с Dispatchers.IO. По-добре използвайте Ktor Client с вградена поддръжка за корутини.
Таймаутът се настройва чрез RetryPolicy. По подразбиране DefaultRetryPolicy използва таймаут от 2,5 секунди и един повторен опит. Промяна на параметрите: request.retryPolicy = DefaultRetryPolicy(10000, 1, 1.0f) — 10 секунди таймаут, един опит.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също