Volley — یک کتابخانه شبکه برای اندروید است که توسط گوگل برای اجرای کارآمد درخواستهای HTTP و بارگذاری تصاویر توسعه یافته است. این کتابخانه به طور خودکار مدیریت پool رشتهها، کش کردن پاسخها و اولویتبندی درخواستها را انجام میدهد. به گزارش Google, 2025، Volley انتخابی محبوب برای پروژههایی باقی میماند که نیاز به شروع سریع بدون پیکربندی وابستگیهای پیچیده دارند.
نکات اصلی
Volley — کتابخانهای برای ارتباطات شبکه در برنامههای اندروید است که توسط گوگل در کنفرانس I/O 2013 معرفی شد. نام Volley به معنی «تیرباران» است — این کتابخانه برای اجرای چندین درخواست سریع موازی طراحی شده که برای برنامههای UI-محور که سرعت پاسخگویی رابط در آنها مهم است، مشخصه هستند.
Volley به عنوان راهحلی برای مشکلات HttpURLConnection و AsyncTask ایجاد شد: مدیریت دستی رشتهها، عدم وجود کش، دشواری اولویتبندی درخواستها و کد حجیم. گوگل 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 پردازش میشوند.
پس از اجرای درخواست، نتیجه از طریق Handler به رشته اصلی (UI thread) تحویل داده میشود. 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 برخلاف OkHttp یا Dio پشتیبانی داخلی از multipart/form-data ندارد.
محدودیتهای Volley هنگام کار با پاسخهای بزرگ آشکار میشود. Volley کل پاسخ را قبل از تحویل به callback در حافظه بارگذاری میکند که میتواند برای فایلهای JSON بزرگتر از 10 تا 20 مگابایت باعث OutOfMemoryError شود. برای بارگذاری فایلهای بزرگ 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 — یک کلاس wrapper بر روی RequestQueue است که برای بارگذاری تصاویر بهینهسازی شده است. این کلاس از کش حافظه (LruCache) پشتیبانی میکند و به طور خودکار درخواستها را هنگام استفاده مجدد از ImageView در لیستهای RecyclerView لغو میکند. ImageLoader همچنین تصاویر را به اندازه View مقیاس میکند و در حافظه صرفهجویی میکند.
NetworkImageView — یک View سفارشی است که با ImageLoader ادغام میشود و به طور خودکار بارگذاری را مدیریت میکند: در هنگام بارگذاری placeholder قرار میدهد، در صورت خرابی با خطا جایگزین میکند و هنگام خروج View از صفحه درخواست را لغو میکند. DefaultImageUrlLoader تصویر را با URL بارگذاری کرده و در LruCache برای نمایش مجدد سریع ذخیره میکند.
برای استفاده از ImageLoader کافی است یک نمونه از طریق ImageLoader(queue, ImageCache) ایجاد کنید، جایی که ImageCache پیادهسازی اینترفیس ImageCache با LruCache در داخل است. NetworkImageView در XML از طریق متد setImageUrl() به ImageLoader متصل میشود و تمام بارگذاری به طور کاملاً خودکار بدون کد اضافی برای مدیریت placeholder و خطاها انجام میشود.
ایجاد RequestQueue در هر Activity — اشتباه رایجی که منجر به تکرار رشتهها و سردرگمی در کش میشود. توصیه میشود RequestQueue یک بار در Application یا از طریق کلاس singleton ایجاد شود. در غیر این صورت هر صفحه pool رشتههای خود را خواهد داشت و کش برای هر صف جداگانه ذخیره میشود.
نادیده گرفتن لغو درخواستها هنگام چرخش صفحه. هنگام تغییر پیکربندی، Activity دوباره ایجاد میشود و callbackهای Activity قدیمی در حافظه باقی میمانند. این منجر به نشت و تلاش برای بهروزرسانی View از بین رفته میشود. همیشه درخواستها را در onStop() از طریق cancelAll() با تگ مخصوص Activity لغو کنید.
Volley از HTTP/2 و کروتین پشتیبانی نمیکند — این یک اشتباه استفاده نیست، بلکه محدودیت معماری است. Volley در سال 2013 ایجاد شده و از پروتکلهای مدرن و کروتینهای Kotlin پشتیبانی نمیکند. گوگل برای پروژههای جدید استفاده از Retrofit + OkHttp را توصیه میکند. Volley فقط برای پشتیبانی از پروژههای legacy یا برنامههای ساده با حداقل نیازمندیهای شبکه مناسب است.
سوالات متداول
Volley برای پروژههای جدید منسوخ شده است — گوگل کتابخانه را از سال 2017 بهروزرسانی نکرده است. برای برنامههای مدرن از Retrofit + OkHttp یا Ktor Client استفاده کنید. Volley فقط برای پشتیبانی از کد legacy موجود یا در پروژههای آموزشی ساده با حداقل وظایف شبکه قابل استفاده است.
عدم پشتیبانی از فناوریهای مدرن: HTTP/2، کروتینهای Kotlin، چندپلتفرمی و سریالسازی تایپشده. Volley از JSONObject و JSONArray بدون تایپ استفاده میکند که در صورت عدم تطابق ساختار JSON با انتظارات منجر به خطاهای runtime میشود.
از طریق ImageLoader و NetworkImageView. ImageLoader از LruCache برای کش کردن تصاویر در حافظه استفاده میکند و به طور خودکار درخواستها را هنگام استفاده مجدد از View لغو میکند. NetworkImageView در هنگام بارگذاری placeholder نشان میدهد و آن را با تصویر آماده یا نشانگر خطا جایگزین میکند.
از نظر فنی بله — از طریق wrapper suspendCoroutine { } روی callbackهای Volley. اما این مزیتی ندارد، زیرا Volley از لغو با لغو کروتین پشتیبانی نمیکند و مستقیماً با Dispatchers.IO کار نمیکند. بهتر است از Ktor Client با پشتیبانی بومی کروتین استفاده کنید.
تایماوت از طریق RetryPolicy تنظیم میشود. به طور پیشفرض DefaultRetryPolicy از تایماوت 2.5 ثانیه و یک تلاش مجدد استفاده میکند. تغییر پارامترها: request.retryPolicy = DefaultRetryPolicy(10000, 1, 1.0f) — 10 ثانیه تایماوت، یک تلاش.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید