Hướng dẫn sử dụng thư viện Volley trong Android

Volley được Google giới thiệu vào khoảng tháng 6/2013. Volley là một thư viện dùng để send và recieve response từ Server sử dụng giao thức HTTP.

Volley có các điểm nổi bật dưới đây:

  • Tự động lập lịch (scheduling) cho các request.
  • Caching Response.
  • Hỗ trợ set độ ưu tiên cho các request (priority).
  • Hỗ trợ nhiều kết quả trả về (String, JSONObject, JSONArray, Bitmap…)
  • Có thể huỷ Request.

Các class sử dụng trong Volley:

RequestQueue: Là hằng đợi giữ các Request.

Request: là lớp cơ sở của các Request trong Volley, chứa thông tin về request HTTP.

StringRequest: Kết thừa từ Request, là class đại diện cho request trả về String.

JSONObjectRequest: Là HTTP request có kết quả trả về là JSONObject.

JSONArrayRequest: Là HTTP request có kết quả trả về là JSONArray.

ImageRequest: Là HTTP request có kết quả trả về là Bitmap.

Ngoài ra chúng ta có thể tạo custom request. Nhưng trong phạm vi bài viết tôi không giới thiệu.

Các bạn cói thể xem video giới thiệu Volley tại Goolge IO/2013.

Dưới đây là mô hình làm việc của Volley:

Mô hình làm việc của Volley
Mô hình làm việc của Volley

Sử dụng thư viện Volley

Trước tiên chúng ta phải import thư viện này vào Android Studio. Copy và paste dòng dưới đây và dependencies trong file build.gradle của module app:

compile 'com.android.volley:volley:1.0.0'

Nhấn Async Now để Android Studio download và nạp thư viện vào project.

Để sử dụng Volley chúng ta 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 Volley

Việc sử dụng Volley rất đơn giản, các bạn chỉ cần tạo một RequestQueue bằng lệnh

RequestQueue mRequestQueue = Volley.newRequestQueue(context);

Phương thức này về một RequestQueue. Khi đã có RequestQueue chúng ta chỉ cần các loại Request và add các request đó vào RequestQueue.

mRequestQueue.add(request);

Chúng ta thấy rằng nếu tôi gọi Volley.newRequestQueue(context); n lần thì có n RequestQueue được tạo ra. Ứng dụng của tôi chỉ cần duy nhất một RequestQueue dử dụng cho toàn app (Activity, Fragment, Service…) Vì vậy, tôi sử dụng Singleton để thiết kết lớp VolleySingleton có nhiệm vụ quản lý RequestQueue như sau:

class VolleySingleton {

    private static final String TAG = "VolleySingleton";
    private static VolleySingleton sInstance;
    private RequestQueue mRequestQueue;

    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 Volley

GET StringRequest Volley:

String url = "https://google.com.vn";
        StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.e(TAG, "StringRequest onResponse: " + response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "StringRequest onErrorResponse: " + error.getMessage());
            }
        });

POST StringRequest Volley:

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;
            }
        };

Độ ưu tiên của Request:

Trong Volley, Request có thể mang các giá trị Priority 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 Request trong Volley có gía trị là NORMAL.

Để set giá trị ưu tiên cho Request các bạn 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 đều tương tự như với StringRequest. Contructor sẽ có những thành phần dưới đây:

  • Method POST, GET.
  • Contructor truyền vào url của request
  • Hai Listener là Response.Listener và Response.ErrorListener

JSONObjectRequest Volley

Request có response trả về là JSONObject.

Nếu Request thành công chúng ta có thể lấy ra đối tượng JSONObject trong phương thức onResponse. Ngược lại chúng ta 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, "JsonObjectRequest onResponse: " + response.getString("ip").toString());
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "JsonObjectRequest onErrorResponse: " + error.getMessage());
            }
        });

JSONArrayRequest Volley

Tương tự như JSONObjectRequest nhưng JSONArrayRequest trả về một JSONArray nếu thành công trong phương thức onResponse.

JsonArrayRequest jsonArrayRequest = new JsonArrayRequest("http://dev.ntcde.com/news/api.php", new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                Log.e(TAG, "JsonArrayRequest onResponse: " + response.toString());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "JsonArrayRequest onErrorResponse: " + error.getMessage());
            }
        });

ImageRequest Volley

ImageRequest trả về response là một bitmap nếu thành công. Ngược lại trả về lỗi trong phương thức onErrorResponse.

ImageRequest imageRequest = new ImageRequest("https://ntcde.com/wp-content/uploads/2016/10/take-a-selfie-with-js.png", new Response.Listener<Bitmap>() {
            @Override
            public void onResponse(Bitmap response) {
                Log.e(TAG, "ImageRequest onResponse: " + response.toString());
            }
        }, 0, 0, null, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "ImageRequest onErrorResponse: " + error.getMessage());
            }
        });

Add Request to RequestQueue Volley

Để tiến hành send request đến server chúng ta cần phải add 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);

Source code MainActivity.java

package ntc.dev4u.com.myapplication;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
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 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 request Method.GET
        volleyStringRequest("NTCDE.COM", "[email protected]", "https://ntcde.com/wp-content/uploads/2016/12/cropped-2dev4u.comNotes-of-Developer-1.png");

        //JsonObject request Method.GET
        volleyJsonObjectRequest();

        //JsonArray request Method.GET
        volleyJsonArrayRequest();

        //Image request
        volleyImageRequest();
    }

    private void volleyImageRequest() {
        ImageRequest imageRequest = new ImageRequest("https://ntcde.com/wp-content/uploads/2016/10/take-a-selfie-with-js.png", new Response.Listener<Bitmap>() {
            @Override
            public void onResponse(Bitmap response) {
                Log.e(TAG, "ImageRequest onResponse: " + response.toString());
            }
        }, 0, 0, null, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "ImageRequest onErrorResponse: " + error.getMessage());
            }
        });
        VolleySingleton.getInstance(this).getRequestQueue().add(imageRequest);
    }

    private void volleyJsonArrayRequest() {
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest("http://dev.ntcde.com/news/api.php", new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                Log.e(TAG, "JsonArrayRequest onResponse: " + response.toString());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "JsonArrayRequest onErrorResponse: " + error.getMessage());
            }
        });
        VolleySingleton.getInstance(this).getRequestQueue().add(jsonArrayRequest);
    }

    private void volleyJsonObjectRequest() {
        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, "JsonObjectRequest onResponse: " + response.getString("ip").toString());
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "JsonObjectRequest onErrorResponse: " + error.getMessage());
            }
        });
        VolleySingleton.getInstance(this).getRequestQueue().add(jsonObjectRequest);
    }

    private void volleyStringRequest(final String name, final String email, final String avatar) {
        StringRequest stringRequest = new StringRequest(Request.Method.GET,
                "http://dev.ntcde.com/news/api.php?email=" + email,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.e(TAG, response.toString());
                        if (!response.equals("User doesn't exist")) {
                            // When user exists will return id_user
                            Log.e(TAG, "User is exists: id= " + response);
                        } else {
                            volleyPostStringRequest(name, email, avatar);
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("Volley", error.getMessage());
            }
        });

        VolleySingleton.getInstance(this).getRequestQueue().add(stringRequest);
    }

    //String request Method.POST
    private void volleyPostStringRequest(final String name, final String email, final String avatar) {
        StringRequest insertRequest = new StringRequest(Request.Method.POST, "http://dev.ntcde.com/news/api.php", new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.e(TAG, "StringRequest Post" + response.toString());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, error.toString());
            }
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                params.put("email", email);
                params.put("name", name);
                params.put("avatar", avatar);

                return params;
            }
        };
        VolleySingleton.getInstance(this).getRequestQueue().add(insertRequest);
    }
}

Kết quả khi chạy project:

03-28 15:05:53.141 5157-5157/ntc.dev4u.com.myapplication E/MainActivity: ImageRequest onResponse: android.graphics.Bitmap@23828f5
03-28 15:05:53.340 5157-5157/ntc.dev4u.com.myapplication E/MainActivity: StringRequest onResponse: User doesn't exist
03-28 15:05:54.078 5157-5157/ntc.dev4u.com.myapplication E/MainActivity: JsonObjectRequest onResponse: 116.99.161.158
03-28 15:05:54.303 5157-5157/ntc.dev4u.com.myapplication E/MainActivity: JsonArrayRequest onResponse: [{"id_ca":"1","name_ca":"Thể thao"},{"id_ca":"2","name_ca":"Giải trí"},{"id_ca":"3","name_ca":"Pháp luật"},{"id_ca":"4","name_ca":"Giáo dục"},{"id_ca":"5","name_ca":"Sức khỏe"},{"id_ca":"6","name_ca":"Khoa học"},{"id_ca":"7","name_ca":"Kinh doanh"},{"id_ca":"8","name_ca":"Du lịch"}]
03-28 15:05:54.429 5157-5157/ntc.dev4u.com.myapplication E/MainActivity: StringRequest Post{"response":[{"id_user":"9","email":"[email protected]","name":"NTCDE.COM","avatar":"http://ntcde.com/wp-content/uploads/2016/12/cropped-2dev4u.comNotes-of-Developer-1.png"}],"status":"Insert user success"}

Trong project, sử dụng phương thức POST StringRequest, để demo phương thức này mình đã code web service bằng PHP và MYSQL , trong android mình đã dùng Volley để parse json và hiển thị kết quả.

Trên đây tôi đã hướng dẫn các bạn cách sử dụng thư viện Volley để send và nhận response từ Server thông sử dụng giao thức HTTP. Hy vọng bài viết giúp ích cho tất cả các bạn trong học tập cũng như công việc.

Project on Githubhttps://github.com/trongcong/VolleyDemo

Tham khảo: http://eitguide.com/thao-tac-voi-network-trong-android-su-dung-thu-vien-volley

Gom Marker trong Android với Google Maps Android API – Google Maps Android Marker Clustering Utility Sử dụng SwipeRefreshLayout trong ứng dụng Android Hướng dẫn tạo Material Dialog Bottom Sheet Android Tạo context menu trong Android – ActionBar ActionMode.CallBack Example Retrofit và Volley thư viện nào tốt hơn Tạo Web Service bằng PHP và MYSQL cho ứng dụng di động – Part 2 Tạo Web Service bằng PHP và MYSQL cho ứng dụng di động – Part 1 Hàm chuyển đổi Timestamp thành Datetime trong Android và JavaScript Design Patterns là gì? Tạo Project Android theo mẫu Design Patterns(Part 2) Design Patterns là gì? Tạo Project Android theo mẫu Design Patterns(Part 1)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.