Volley — nó là gì, các tính năng của thư viện mạng Google

Tác giả: IT Sectr Đã đăng: 2026-03-07 Thời gian đọc: 8 phút

Volley là thư viện mạng dành cho Android do Google phát triển để thực hiện các yêu cầu HTTP hiệu quả và tải hình ảnh. Thư viện tự động quản lý một nhóm luồng (thread pool), lưu trữ phản hồi vào bộ nhớ đệm và ưu tiên các yêu cầu. Theo Google, 2025, Volley vẫn là lựa chọn phổ biến cho các dự án cần khởi động nhanh mà không cần cấu hình các phụ thuộc phức tạp.

Những điểm chính

  • Volley — thư viện mạng của Google cho Android với quản lý luồng tự động
  • RequestQueue — lớp trung tâm để tổ chức hàng đợi và thực hiện các yêu cầu
  • ImageLoader — công cụ tích hợp để tải hình ảnh với bộ nhớ đệm
  • Ưu tiên hóa — hỗ trợ ưu tiên yêu cầu bình thường, thấp và cao
  • Bộ nhớ đệm — bộ nhớ đệm đĩa và bộ nhớ tích hợp cho các yêu cầu lặp lại

Volley là gì?

Volley là một thư viện giao tiếp mạng cho các ứng dụng Android, được Google giới thiệu tại hội nghị I/O 2013. Tên Volley có nghĩa là “một loạt bắn” — thư viện được thiết kế để thực hiện nhiều yêu cầu nhanh song song, đặc trưng của các ứng dụng hướng UI nơi tốc độ phản hồi giao diện là quan trọng.

Volley được tạo ra như một giải pháp cho các vấn đề của HttpURLConnection và AsyncTask: quản lý luồng thủ công, thiếu bộ nhớ đệm, sự phức tạp trong việc ưu tiên yêu cầu và mã phức tạp. Google định vị Volley như một thư viện cho các hoạt động “fire-and-forget” — các yêu cầu nhỏ có kết quả hiển thị ngay lập tức trong giao diện.

Kiến trúc Volley bao gồm ba thành phần chính: RequestQueue (trình quản lý hàng đợi), CacheDispatcher (luồng cho các phản hồi được lưu trong bộ nhớ đệm) và NetworkDispatcher (các luồng mạng). Kiến trúc này tự động phân phối các yêu cầu: đầu tiên kiểm tra bộ nhớ đệm, và chỉ khi không có mới thực hiện yêu cầu mạng. Điều này giảm độ trễ cho dữ liệu lặp lại từ 50–80%.

Volley hoạt động như thế nào

RequestQueue là lớp trung tâm của Volley. Các đối tượng Request<T> được thêm vào nó, và hàng đợi tự động phân phối chúng giữa hai loại luồng: CacheDispatcher (một luồng, xử lý các yêu cầu có thể lưu vào bộ nhớ đệm) và NetworkDispatcher (nhiều luồng, thực hiện các yêu cầu HTTP thực tế). Theo mặc định, Volley tạo 4 luồng mạng.

Khi một yêu cầu được thêm vào, RequestQueue kiểm tra xem nó có thể được phục vụ từ bộ nhớ đệm hay không. Nếu bộ nhớ đệm chứa phản hồi cập nhật, CacheDispatcher trả về ngay lập tức mà không cần yêu cầu mạng. Nếu bộ nhớ đệm cũ hoặc không có, yêu cầu được chuyển đến NetworkDispatcher. Ưu tiên yêu cầu (low, normal, high, immediate) xác định thứ tự xử lý trong hàng đợi — các yêu cầu có ưu tiên high được xử lý trước các yêu cầu normal.

Sau khi yêu cầu được thực hiện, kết quả được chuyển đến luồng chính (UI thread) thông qua Handler. Volley tự động chuyển các callback onResponse() và onErrorResponse() sang luồng chính, do đó giao diện có thể được cập nhật trực tiếp trong callback mà không cần chuyển đổi luồng bổ sung. Điều này đơn giản hóa mã và loại bỏ toàn bộ một lớp lỗi luồng.

Một tính năng khác của Volley là tự động loại bỏ trùng lặp yêu cầu. Nếu hai yêu cầu GET giống hệt nhau đến cùng một URL với cùng tham số được thêm vào hàng đợi, Volley chỉ thực hiện một trong số chúng và trả về cùng một phản hồi cho cả hai callback. Điều này đặc biệt hữu ích cho các màn hình nơi nhiều thành phần độc lập yêu cầu cùng một dữ liệu — ví dụ, hồ sơ người dùng cần đồng thời cho cả tiêu đề và một fragment cài đặt.

Vòng đời yêu cầu trong Volley

Mỗi yêu cầu trải qua một chuỗi các bước: tạo Request, thêm vào RequestQueue, kiểm tra bộ nhớ đệm (CacheDispatcher), thực hiện yêu cầu HTTP (NetworkDispatcher), phân tích phản hồi thông qua Response.Listener, chuyển kết quả đến luồng UI. Khi một yêu cầu bị hủy (cancel), RequestQueue xóa nó khỏi hàng đợi và ngăn chặn việc gọi callback.

Volley cũng hỗ trợ RetryPolicy, xác định số lần thử lại khi thất bại. DefaultRetryPolicy theo mặc định thực hiện một lần thử lại với thời gian chờ 2.5 giây. Đối với các kết nối không ổn định, số lần thử lại có thể tăng lên 3 và thời gian chờ lên 10 giây. RetryPolicy tùy chỉnh được thực hiện thông qua giao diện RetryPolicy với các phương thức getCurrentTimeout, getCurrentRetryCount và retry.

Các loại yêu cầu Volley

Volley cung cấp các loại yêu cầu có sẵn cho các định dạng dữ liệu phổ biến. Mỗi loại triển khai lớp trừu tượng Request<T> và xác định một phương thức để phân tích phản hồi. Đối với các định dạng tùy chỉnh, bạn có thể tạo loại của riêng mình bằng cách ghi đèn phương thức parseNetworkResponse.

Loại yêu cầuLoại trả vềMục đích
StringRequestStringNhận phản hồi văn bản thô
JsonObjectRequestJSONObjectPhân tích đối tượng JSON
JsonArrayRequestJSONArrayPhân tích mảng JSON
ImageRequestBitmapTải và giải mã hình ảnh
ClearCacheRequestXóa bộ nhớ đệm Volley

Yêu cầu tùy chỉnh

Để làm việc với Gson hoặc Kotlinx Serialization, bạn có thể tạo một Request<T> tùy chỉnh sử dụng trình phân tích đã chọn trong parseNetworkResponse. Điều này cho phép nhận các đối tượng được nhập trực tiếp, tránh việc phân tích JSONObject thủ công. Cách tiếp cận này đặc biệt hữu ích cho các dự án đã sử dụng tuần tự hóa qua Gson hoặc Moshi.

Để gửi dữ liệu, Volley hỗ trợ ba loại nội dung: JSONObject (thông qua JsonObjectRequest với phương thức POST), Form-encoded (thông qua HashMap<String, String> trong hàm tạo) và Multipart (thông qua MultipartRequest tùy chỉnh). Các yêu cầu Multipart hữu ích để tải lên hình ảnh và tệp nhưng yêu cầu triển khai thủ công vì Volley không có hỗ trợ tích hợp cho multipart/form-data, không giống như OkHttp hoặc Dio.

Các hạn chế của Volley trở nên rõ ràng khi làm việc với các phản hồi lớn. Volley tải toàn bộ phản hồi vào bộ nhớ trước khi chuyển đến callback, điều này có thể gây ra OutOfMemoryError cho các tệp JSON lớn hơn 10–20 MB. Để tải xuống các tệp lớn, Volley không phù hợp — hãy sử dụng DownloadManager hoặc OkHttp với ResponseBody phát trực tuyến. Volley cũng không hỗ trợ tiếp tục tải xuống bị gián đoạn (tiêu đề Range) và không hoạt động với các giao thức phát trực tuyến như Server-Sent Events hoặc WebSocket theo thời gian thực.

Ví dụ mã Volley trong Java và Kotlin

Hãy xem ví dụ cơ bản — StringRequest để lấy dữ liệu từ máy chủ. Đầu tiên, một RequestQueue được tạo thông qua Volley.newRequestQueue(context). Sau đó, một yêu cầu được hình thành với URL và các callback thành công và lỗi.

kotlin
val queue = Volley.newRequestQueue(context)

val request = StringRequest(
    Request.Method.GET,
    "https://api.github.com/users/octocat",
    { response ->
        println("Phản hồi: $response")
    },
    { error ->
        println("Lỗi: ${error.message}")
    }
)

queue.add(request)

Đối với yêu cầu JSON, JsonObjectRequest được sử dụng, tự động phân tích phản hồi thành JSONObject. Volley hỗ trợ các yêu cầu GET và POST. Đối với POST, một JSONObject được chuyển trong nội dung yêu cầu.

kotlin
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("Đã tạo: ${response.getString("id")}")
    },
    { println("Lỗi: $it") }
)

queue.add(request)

Hủy yêu cầu

Để hủy một yêu cầu, phương thức cancel() hoặc hủy theo nhóm theo thẻ được sử dụng. Khi hủy, Volley không gọi onResponse hoặc onErrorResponse, điều này ngăn chặn cập nhật giao diện sau khi rời khỏi màn hình. Điều này quan trọng để ngăn ngừa rò rỉ bộ nhớ trong Activity và Fragment.

kotlin
request.tag = "profile_request"
queue.add(request)

// Hủy khi rời khỏi màn hình
queue.cancelAll("profile_request")

ImageLoader và NetworkImageView

ImageLoader là một lớp bao bọc quanh RequestQueue, được tối ưu hóa để tải hình ảnh. Nó hỗ trợ bộ nhớ đệm (LruCache) và tự động hủy các yêu cầu khi ImageView được sử dụng lại trong danh sách RecyclerView. ImageLoader cũng thay đổi kích thước hình ảnh để vừa với kích thước View, tiết kiệm bộ nhớ.

NetworkImageView là một View tùy chỉnh tích hợp với ImageLoader và tự động quản lý việc tải: hiển thị placeholder trong khi tải, thay thế bằng lỗi khi thất bại và hủy yêu cầu khi View rời khỏi màn hình. DefaultImageUrlLoader tải hình ảnh theo URL và lưu trữ nó trong LruCache để hiển thị lại nhanh chóng.

Để sử dụng ImageLoader, chỉ cần tạo một thể hiện thông qua ImageLoader(queue, ImageCache), trong đó ImageCache là một triển khai của giao diện ImageCache với LruCache bên trong. NetworkImageView trong bố cục XML được liên kết với ImageLoader thông qua phương thức setImageUrl(), và toàn bộ việc tải diễn ra hoàn toàn tự động mà không cần mã bổ sung để xử lý placeholder và lỗi.

Các lỗi thường gặp khi làm việc với Volley

Tạo RequestQueue trong mỗi Activity là một lỗi phổ biến dẫn đến trùng lặp luồng và nhầm lẫn bộ nhớ đệm. Nên tạo RequestQueue một lần trong Application hoặc thông qua một lớp singleton. Nếu không, mỗi màn hình sẽ có nhóm luồng riêng và bộ nhớ đệm sẽ được lưu trữ riêng cho mỗi hàng đợi.

Bỏ qua việc hủy yêu cầu khi xoay màn hình. Khi cấu hình thay đổi, Activity được tạo lại và các callback của Activity cũ tiếp tục tồn tại trong bộ nhớ. Điều này dẫn đến rò rỉ và cố gắng cập nhật một View đã bị hủy. Luôn hủy các yêu cầu trong onStop() thông qua cancelAll() với một thẻ cụ thể cho Activity.

Volley không hỗ trợ HTTP/2 và coroutine — đây không phải là lỗi sử dụng mà là một hạn chế về kiến trúc. Volley được tạo ra vào năm 2013 và không hỗ trợ các giao thức hiện đại và coroutine Kotlin. Đối với các dự án mới, Google khuyến nghị sử dụng Retrofit + OkHttp. Volley chỉ phù hợp để hỗ trợ các dự án kế thừa hoặc các ứng dụng đơn giản với yêu cầu mạng tối thiểu.

Câu hỏi thường gặp

Có đáng để sử dụng Volley vào năm 2025 không?

Volley đã lỗi thời cho các dự án mới — Google đã không cập nhật thư viện kể từ năm 2017. Đối với các ứng dụng hiện đại, hãy sử dụng Retrofit + OkHttp hoặc Ktor Client. Volley chỉ có thể được sử dụng để hỗ trợ mã kế thừa hiện có hoặc trong các dự án giáo dục đơn giản với các tác vụ mạng tối thiểu.

Nhược điểm chính của Volley là gì?

Thiếu hỗ trợ cho các công nghệ hiện đại: HTTP/2, coroutine Kotlin, phát triển đa nền tảng và tuần tự hóa có kiểu. Volley sử dụng JSONObject và JSONArray mà không có kiểu, dẫn đến lỗi runtime khi cấu trúc JSON không khớp với mong đợi.

Volley xử lý hình ảnh như thế nào?

Thông qua ImageLoaderNetworkImageView. ImageLoader sử dụng LruCache để lưu trữ hình ảnh trong bộ nhớ đệm và tự động hủy các yêu cầu khi các view được sử dụng lại. NetworkImageView hiển thị placeholder trong khi tải và thay thế nó bằng hình ảnh đã tải hoặc chỉ báo lỗi.

Có thể sử dụng Volley với coroutine không?

Kỹ thuật là có — thông qua một wrapper suspendCoroutine { } trên các callback của Volley. Nhưng điều này không mang lại lợi ích vì Volley không hỗ trợ hủy dựa trên việc hủy coroutine và không làm việc trực tiếp với Dispatchers.IO. Tốt hơn nên sử dụng Ktor Client với hỗ trợ coroutine gốc.

Làm thế nào để cấu hình thời gian chờ trong Volley?

Thời gian chờ được cấu hình thông qua RetryPolicy. Theo mặc định, DefaultRetryPolicy sử dụng thời gian chờ 2,5 giây và một lần thử lại. Để thay đổi tham số: request.retryPolicy = DefaultRetryPolicy(10000, 1, 1.0f) — 10 giây thời gian chờ, một lần thử.

Tổng kết

  • Volley — thư viện mạng của Google với quản lý luồng tự động và bộ nhớ đệm
  • RequestQueue phân phối các yêu cầu giữa CacheDispatcher và NetworkDispatcher
  • StringRequest, JsonObjectRequest và ImageRequest — các loại yêu cầu tích hợp của Volley
  • ImageLoader tải hình ảnh với bộ nhớ đệm qua LruCache
  • Ưu tiên hóa yêu cầu (low, normal, high) kiểm soát thứ tự thực hiện trong hàng đợi
  • Volley đã lỗi thời — cho các dự án mới, hãy sử dụng Retrofit + OkHttp hoặc Ktor
  • Hủy yêu cầu theo thẻ là bắt buộc khi xoay màn hình để ngăn rò rỉ bộ nhớ

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm