Giới thiệu
Volley là thư viện dùng để gửi và nhận phản hồi từ server sử dụng giao thức HTTP được Google giới thiệu vào tháng 6/2013. Volley có các điểm nổi bật dưới đây:
- Tự động lập lịch cho các yêu cầu.
- Phản hồi vào bộ nhớ đệm.
- Hỗ trợ đặt độ ưu tiên cho các yêu cầu.
- Hỗ trợ nhiều kết quả trả về (
String
,JSONObject
,JSONArray
,Bitmap
, ...). - Có thể hủy Request.
Các lớp sử dụng trong Volley:
RequestQueue
: hàng đợi để giữ các yêu cầu.Request
: lớp cơ sở của cácRequest
trong Volley và chứa thông tin về yêu cầu HTTP.StringRequest
: kế thừa từRequest
và là lớp đại diện cho yêu cầu trả về chuỗi.JSONObjectRequest
: là HTTP yêu cầu, có phản hồi trả về làJSONObject
.JSONArrayRequest
: là HTTP yêu cầu, có phản hồi trả về làJSONArray
.ImageRequest
: là HTTP yêu cầu, có phản hồi trả về làBitmap
.

Sử dụng thư viện Volley
Trước tiên import thư viện này vào Android Studio. Sau đó sao chép và dán dòng dưới đây vào dependencies trong file build.gradle của module app:
compile 'com.android.volley:volley:1.0.0'
Nhấn Sync Now để Android Studio tải và nạp thư viện vào project.
Để sử dụng Volley, phải cấp quyền internet trong AndroidManifest.xml như sau:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
RequestQueue
Để sử dụng Volley chỉ cần tạo 1 RequestQueue
bằng lệnh:
RequestQueue mRequestQueue = Volley.newRequestQueue(context);
Khi đã có RequestQueue
, chỉ cần thêm các yêu cầu vào RequestQueue
.
mRequestQueue.add(request);
Nếu gọi Volley.newRequestQueue(context)
n lần thì có n RequestQueue
được tạo ra. Ứng dụng chỉ cần duy nhất 1 RequestQueue
sử dụng cho toàn app (Activity, Fragment, Service, ...). Vì vậy sử dụng Singleton để thiết kế lớp VolleySingleton
để có nhiệm vụ quản lý RequestQueue
như sau:
public class VolleySingleton { private static final String TAG = "VolleySingleton"; private RequestQueue mRequestQueue; private static VolleySingleton sInstance; private VolleySingleton(Context context) { if (mRequestQueue == null) mRequestQueue = Volley.newRequestQueue(context.getApplicationContext()); } public static synchronized VolleySingleton getInstance(Context context) { if (sInstance == null) sInstance = new VolleySingleton(context); return sInstance; } public RequestQueue getRequestQueue() { return mRequestQueue; } }
StringRequest
Phương thức GET
String url = "https://www.google.com.vn/"; StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { Log.e(TAG, "onResponse: " + response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } } );
Phương thức POST
Với POST
phải override lại phương thức getParam()
và đặt các key, value như dưới đây:
String url = "https://eitguide.net/"; StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() { @Override public void onResponse(String response) { Log.e(TAG, "onResponse: " + response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } } ) { @Override protected Map<String, String> getParams() throws AuthFailureError { HashMap<String, String> params = new HashMap<>(); params.put("para1", "value1"); params.put("para1", "value2"); return params; } };
Độ ưu tiên của yêu cầu
Trong Volley, yêu cầu mang các giá trị ưu tiên như dưới đây:
/** * Priority values. Requests will be processed from higher priorities to * lower priorities, in FIFO order. */ public enum Priority { LOW, NORMAL, HIGH, IMMEDIATE }
Với các mức độ ưu tiên tăng dần và mặc định yêu cầu trong Volley có giá trị là NORMAL
.
Để đặt giá trị ưu tiên cho yêu cầu, phải override lại phương thức getPriority()
:
String url = "http://example.com/"; StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() { @Override public void onResponse(String response) { Log.e(TAG, "onResponse: " + response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } } ) { @Override protected Map<String, String> getParams() throws AuthFailureError { HashMap<String, String> params = new HashMap<>(); params.put("para1", "value1"); params.put("para1", "value2"); return params; } @Override public Priority getPriority() { return Priority.HIGH; } };
Cách tạo Request
đối với JSONObjectRequest
, JSONArrayObject
, ImageRequest
tương tự như StringRequest
. Constructor sẽ có những thành phần sau:
- Các phương thức
POST
,GET
. - Constructor truyền vào url của yêu cầu.
- 2 listener gồm
Response
,Listener
, vớiResponse.ErrorListener
.
JSONObjectRequest
Request
có phản hồi trả về là JSONObject.
Nếu Request
thành công thì có thể lấy ra đối tượng JSONObject
trong phương thức onResponse()
. Ngược lại, sẽ có thông tin lỗi trong phương thức onErrorResponse()
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, "https://api.ipify.org/?format=json", null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { Log.e(TAG, "onResponse: " + response.getString("ip").toString()); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } } );
JSONArrayRequest
Nếu thành công trong phương thức onResponse()
thì trả về 1 JSONArray.
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest("http://eitguide.com/jsonarray.php", new Response.Listener<JSONArray>() { @Override public void onResponse(JSONArray response) { Log.e(TAG, "onResponse: " + response.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } } );
ImageRequest
Nếu thành công thì ImageRequest
trả về response
là 1 bitmap, ngược lại thì trả về lỗi trong phương thức onErrorResponse()
ImageRequest imageRequest = new ImageRequest("http://eitguide.com/wp-content/uploads/2016/08/sqlite-android-0.png", new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { Log.e(TAG, "onResponse: " + response); } }, 0, 0, null, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } } );
Add Request vào RequestQueue
Để tiến hành gửi request đến server, cần phải thêm những request vừa tạo ở trên vào RequestQueue
.
VolleySingleton.getInstance(this).getRequestQueue().add(stringRequest); VolleySingleton.getInstance(this).getRequestQueue().add(jsonObjectRequest); VolleySingleton.getInstance(this).getRequestQueue().add(imageRequest); VolleySingleton.getInstance(this).getRequestQueue().add(jsonArrayRequest);
File MainActivity.java
package com.example.nguyennghia.volleydemo; import android.graphics.Bitmap; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import com.android.volley.AuthFailureError; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.ImageRequest; import com.android.volley.toolbox.JsonArrayRequest; import com.android.volley.toolbox.JsonObjectRequest; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; import java.util.Map; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String url = "https://www.google.com.vn/"; StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { Log.e(TAG, "onResponse: " + response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } }); JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, "https://api.ipify.org/?format=json", null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { Log.e(TAG, "onResponse: " + response.getString("id").toString()); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } } ); JsonArrayRequest jsonArrayRequest = new JsonArrayRequest("http://eitguide.com/jsonarray.php", new Response.Listener<JSONArray>() { @Override public void onResponse(JSONArray response) { Log.e(TAG, "onResponse: " + response.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } } ); ImageRequest imageRequest = new ImageRequest("http://eitguide.com/wp-content/uploads/2016/08/sqlite-android-0.png", new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { Log.e(TAG, "onResponse: " + response); } }, 0, 0, null, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse: " + error.getMessage()); } } ); VolleySingleton.getInstance(this).getRequestQueue().add(stringRequest); VolleySingleton.getInstance(this).getRequestQueue().add(jsonObjectRequest); VolleySingleton.getInstance(this).getRequestQueue().add(imageRequest); VolleySingleton.getInstance(this).getRequestQueue().add(jsonArrayRequest); } }
Kết quả khi chạy project:
08-07 00:01:46.427 23636-23636/com.example.nguyennghia.volleydemo E/MainActivity: onResponse: android.graphics.Bitmap@c8cf6d9 08-07 00:01:46.536 23636-23636/com.example.nguyennghia.volleydemo E/MainActivity: onResponse: [{"firstName":"John","lastName":"Doe"},{"firstName":"Anna","lastName":"Smith"},{"firstName":"Peter","lastName":"Jones"}] 08-07 00:01:46.949 23636-23636/com.example.nguyennghia.volleydemo E/MainActivity: onResponse: <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="vi"><head><meta content="width=device-width,minimum-scale=1.0" name="viewport"><meta content="/logos/doodles/2016/2016-doodle-fruit-games-day-2-5749930065920000-hp.gif" itemprop="image"><link href="/images/branding/product/ico/googleg_lodp.ico" rel="shortcut icon"><meta content="Trò chơi chủ đề Hoa quả 2016 - g.co/fruit #GoogleDoodle" property="og:description"><meta content="http://www.google.com/logos/doodles/2016/2016-doodle-fruit-games-day-2-5749930065920000-thp.png" property="og:image"><meta content="450" property="og:image:width"><meta content="163" property="og:image:height"><title>Google</title> <script>(function(){window.google={kEI:'-xemV-XUEIrbvgSrnKKIAQ',kEXPI:'750222,3700212,3700299,3700389,4029815,4031109,4032678,4036509,4036527,4038012,4039268,4041303,4043492,4045841,4048347,4052304,4053261,4058077,4058720,4061155,4061923,4063132,4063220,4063879,4065786,4065873,4066654,4067175,4068550,4068560,4068604,4068850,4069458,4069838,4069840,4069845,4069906,4070060,4070125,4070142,4070230,4070242,4070502,4070598,4071422,4071577,4071606,4071661,4071665,4071772,4071842,4071896,4072128,4072213,4072606,4072645,4072675,4072682,4072774,4073418,4073492,4073889,4074111,4074426,4074539,8300096,8300273,8502184,8502369,8503585,8504931,8505150,8505152,8505259,8505585,8505677,8505796,8505835,8505870,8506066,8506166,10200084,10200096,10201287,10201956,19000435',authuser:0,kscs:'c9c918f0_24'};google.kHL='vi';})();(function(){google.lc=[];google.li=0;google.getEI=function(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute("eid")));)a=a.parentNode;return b||google.kEI};google.getLEI=function(a){for(var b=null;a&&(!a.getAttribute||!(b=a.getAttribute("leid")));)a=a.parentNode;return b};google.https=function(){return"https:"==window.location.protocol};google.ml=function(){return null};google.wl=function(a,b){try{google.ml(Error(a),!1,b)}catch(c){}};google.time=function(){return(new Date).getTime()};google.log=function(a,b,c,e,g){a=google.logUrl(a,b,c,e,g);if(""!=a){b=new Image;var d=google.lc,f=google.li;d[f]=b;b.onerror=b.onload=b.onabort=function(){delete d[f]};window.google&&window.google.vel&&window.google.vel.lu&&window.google.vel.lu(a);b.src=a;google.li=f+1}};google.logUrl=function(a,b,c,e,g){var d="",f=google.ls||"";if(!c&&-1==b.search("&ei=")){var h=google.getEI(e),d="&ei="+h;-1==b.search("&lei=")&&((e=google.getLEI(e))?d+="&lei="+e:h!=google.kEI&&(d+="&lei="+google.kEI))}a=c||"/"+(g||"gen_204")+"?atyp=i&ct="+a+"&cad="+b+d+f+"&zx="+google.time();/^http:/i.test(a)&&google.https()&&(google.ml(Error("a"),!1,{src:a,glmm:1}),a="");return a};google.y={};google.x=function(a,b){google.y[a.id]=[a,b];return!1};google.load=function(a,b,c){google.x({id:a+k++},function(){google.load(a,b,c)})};var k=0;})();(function(){google.c={c:{a:true,d:true,i:false,m:true,n:false}};google.sn='webhp';(function(){var e=function(a,b,c){a.addEventListener?a.removeEventListener(b,c,!1):a.attachEvent&&a.detachEvent("on"+b,c)},g=function(a,b,c){f.push({o:a,v:b,w:c});a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent&&a.attachEvent("on"+b,c)},f=[];google.timers={};google.startTick=function(a,b){var c=b&&google.timers[b].t?google.timers[b].t.start:google.time();google.timers[a]={t:{start:c},e:{},it:{},m:{}};(c=window.performance)&&c.now&&(google.timers[a].wsrt=Math.floor(c.now()))};google.tick=function(a,b,c){google.timers[a]||google.startTick(a);c=c||google.time();b instanceof Array||(b=[b]);for(var d=0;d<b.length;++d)google.timers[a].t[b[d]]=c};google.c.e=function(a,b,c){google.timers[a].e[b]=c};google.bit=function(a,b){google.timers[a]||google.startTick(a);var c=google.timers[a].it[b];c||(c=google.timers[a].it[b]=[]);var d=c.push({s:google.time()})-1;return function(){c[d]&&(c[d].e=google.time())}};google.c.b=function(a){var b=google.timers.load.m;b[a]&&google.wl("ch_mab",{m:a});b[a]=!0};google.c.u=function(a){var b=google.timers.load.m;if(b[a]){b[a]=!1;for(a in b)if(b[a])return;google.csiReport()} 08-07 00:01:47.964 23636-23636/com.example.nguyennghia.volleydemo E/MainActivity: onResponse: 115.79.44.145
Tải source code trong bài viết:
- Tải trực tiếp tại: VolleyDemo-master.zip.
- Tải thông qua Github.