Search…

Thao Tác với Network trong Android Sử Dụng Thư Viện Volley

16/11/20206 min read
Sử dụng thư viện Volley tương tác gửi nhận trong network, gửi nhận HTTP Request, HTTP Response trong Android.

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ác Request 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.
Mô hình làm việc của Volley

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ới Response.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&#417;i ch&#7911; &#273;&#7873; Hoa qu&#7843; 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:

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024