Volley 網路請求框架介紹與使用說明
一、前言
Volley 是一個基於 HTTP 的網路開源庫,讓 Android 應用更快更容易地連線網路,在 GitHub 上可以找到它的源專案。Volley 具有以下優點:
* 自動排程網路請求。
* 支援多併發網路連線。
* 支援快取。
* 支援請求優先順序。
* 支援取消請求,可以取消單個請求,也可以取消包含多個請求的請求塊。
* 支援自定義。
* 支援非同步資料排序功能。
* 支援除錯和具備跟蹤工具。
Volley 適用於 RPC(遠端過程呼叫:Remote Procedure Call)型別操作,例如將搜尋結果頁面作為結構化資料獲取。Volley 可以很容易與所有協議整合,支援原始字串,影象和 JSON。
Volley 不適合大型下載或流媒體操作,因為 Volley 在解析期間將所有響應儲存在記憶體中。對於大型下載操作,可以考慮使用 DownloadManager
。
最簡單新增 Volley 的方法是將以下依賴項新增到應用程式的 build.gradle
檔案中:
dependencies {
...
compile 'com.android.volley:volley:1.1.1'
}
除此之外,你還可以克隆 Volley 專案庫並將其設定為庫專案:
- 通過在命令列鍵入以下內容來克隆專案庫:
git clone https://github.com/google/volley
- 將下載的源作為 Android 庫模組匯入到應用專案中。
二、使用 Volley 傳送請求
使用 Volley 之前,必須將 android.permission.INTERNET
許可權新增到應用的清單中。不然,應用無法連線到網路。
1. 使用 newRequestQueue
Volley 提供了一個便捷的方法 Volley.newRequestQueue
為你設定並啟動 RequestQueue
佇列,該 RequestQueue
使用預設值。例如:
final TextView mTextView = (TextView) findViewById(R.id.text);
// ...
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
mTextView.setText("Response is: "+ response.substring(0,500));
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mTextView.setText("That didn't work!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
Volley 總是在主執行緒上傳遞已解析的響應,這樣可以很方便地使用接收到的資料填充 UI 控制元件。
2. 傳送請求
要傳送請求,只需構建一個請求並使用 add()
將其新增到 RequestQueue
,如上所示。新增請求後,請求將通過網路獲取服務,解析並傳遞其原始響應。
當呼叫 add()
時,Volley 執行一個快取記憶體處理執行緒和一個網路分派執行緒池。當向佇列新增請求時,它會被快取執行緒拾取並進行分類:如果請求可以從快取中獲取服務,則快取響應將在快取執行緒上進行解析,並將解析後的響應在主執行緒上傳遞。如果無法從快取中為請求提供服務,則將其置於網路佇列中。第一個可用的網路執行緒從佇列中獲取請求,執行 HTTP 事務,在子執行緒上解析響應,然後將響應寫入快取,並將解析的響應傳送回主執行緒來進行傳遞。
可以在任意執行緒中新增請求,但響應始終在主執行緒上傳遞。
3. 取消請求
要取消請求,請對 Request
物件呼叫 cancel()
。一旦取消,Volley 保證你的響應處理回撥永遠不會被呼叫。一般可以在 Activity 的 onStop()
方法中取消所有待處理的請求。
但是,這樣的話你必須跟蹤所有正在進行的請求。有一種更簡單的方法:你可以使用一個標記物件與每個請求進行關聯。然後,使用此標記物件獲得取消請求的範圍。例如,使用 Activity 將所有由它發出的請求進行標記,並從 onStop()
中呼叫 requestQueue.cancelAll(this)
。同樣,在 ViewPager 選項卡中使用各自的選項卡標記所有縮圖影象請求,並在滑動時取消,以確保新選項卡不會被另一個選項卡的請求持有。
以下是使用字串標記的示例:
- 定義標記並將其新增到你的請求中。
public static final String TAG = "MyTag";
StringRequest stringRequest; // Assume this exists.
RequestQueue mRequestQueue; // Assume this exists.
// Set the tag on the request.
stringRequest.setTag(TAG);
// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
- 在 Activity 的
onStop()
方法中,取消所有具有此標記的請求。
@Override
protected void onStop () {
super.onStop();
if (mRequestQueue != null) {
mRequestQueue.cancelAll(TAG);
}
}
取消請求時要注意,該請求的響應是否是必要的。
三、設定 RequestQueue
1. 設定網路和快取
RequestQueue 需要兩樣東西都完成它的工作:一個是用於執行請求傳輸的網路,一個是用於處理快取的快取。Volley 工具箱中已經有標準的實現:DiskBasedCache
提供帶有記憶體索引的單檔案響應快取,BasicNetwork
根據你首選的 HTTP 客戶端提供網路傳輸。
BasicNetwork
是 Volley 的預設網路實現。BasicNetwork
必須被用來連線到網路的 HTTP 客戶端初始化。這個客戶端通常是 HttpURLConnection
。
下面程式碼段顯示了初始化 BasicNetwork
的步驟包括設定 RequestQueue
:
RequestQueue mRequestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);
// Start the queue
mRequestQueue.start();
String url ="http://www.example.com";
// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Do something with the response
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// Handle error
}
});
// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
// ...
你可以在任何時候建立 RequestQueue
,並在得到響應後呼叫 stop()
來實現單次請求。
但更常見的情況是建立一個 RequestQueue
的單例,使得它在應用的生命週期內保持執行。
2. 使用單例模式
設定一個 RequestQueue
的單例通常效率最高。推薦的方法是實現封裝 RequestQueue
和其他 Volley 功能的單例類。另一種方法是建立 Application
的子類並在 Application.onCreate()
方法中設定 RequestQueue
,但是這種方法並不推薦,因為靜態單例可以以更模組化的方式提供相同的功能。
一個關鍵概念是 RequestQueue
必須使用 Application
上下文進行例項化,而不是 Activity
上下文。這樣可以確保 RequestQueue
在應用的生命週期內持續使用,而不是每次重新建立 Activtiy
時重新例項化(例如當使用者旋轉裝置時)。
這裡是一個單類,它提供 RequestQueue
和 ImageLoader
功能:
public class MySingleton {
private static MySingleton mInstance;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private static Context mCtx;
private MySingleton(Context context) {
mCtx = context;
mRequestQueue = getRequestQueue();
mImageLoader = new ImageLoader(mRequestQueue,
new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap>
cache = new LruCache<String, Bitmap>(20);
@Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
public static synchronized MySingleton getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySingleton(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
public ImageLoader getImageLoader() {
return mImageLoader;
}
}
以下是使用單例類執行 RequestQueue
操作的一些示例:
// Get a RequestQueue
RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
getRequestQueue();
// ...
// Add a request (in this example, called stringRequest) to your RequestQueue.
MySingleton.getInstance(this).addToRequestQueue(stringRequest);
四、提出標準請求
Volley 支援的常見請求型別:
StringRequest。指定 URL 並接收原始字串作為響應。
JsonObjectRequest 和 JsonArrayRequest(兩個都是 JsonRequest 的子類)。指定 URL 並分別獲取 JSON 物件或陣列作為響應。
如果你的預期響應是這些型別之一,則不必實現自定義請求。
1. 請求 JSON
Volley 為 JSON 請求提供以下類:
JsonArrayRequest
- 使用給定的 URL 獲取 JSONArray 響應體。JsonObjectRequest
- 使用給定的 URL 獲取 JSONObject 響應體,允許將 JSONObject 作為請求體的一部分傳入。
這兩個類都基於公共基類 JsonRequest。下面程式碼段是提取 JSON 資料並在 UI 中將其顯示為文字:
String url = "http://my-json-feed";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
mTextView.setText("Response: " + response.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
}
});
// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest);
五、實現自定義請求
對於那些不支援開箱即用的資料型別,我們需要實現自定義請求型別。
1. 寫一個自定義請求
大多數請求在工具箱中都有現成的實現,如果響應是字串、影象或 JSON,則不需要實現自定義請求。
對於需要實現自定義請求的情況,你只需執行以下操作:
擴充套件
Request<T>
類,其中<T>
表示請求所期望的已解析響應的型別。因此,如果解析後的響應是字串,則通過擴充套件Request<String>
建立自定義請求。實現抽象方法,
parseNetworkResponse()
和deliverResponse()
。
1.1 parseNetworkResponse
對於給定型別(例如字串,影象或 JSON),Response 封裝解析的響應用來傳遞。以下是一個示例實現 parseNetworkResponse()
:
@Override
protected Response<T> parseNetworkResponse(
NetworkResponse response) {
try {
String json = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(gson.fromJson(json, clazz),
HttpHeaderParser.parseCacheHeaders(response));
}
// handle errors
// ...
}
請注意:parseNetworkResponse()
將 NetworkResponse
作為引數 ,其中包含響應有效負載作為 byte []、HTTP 狀態程式碼和響應頭。
自定義實現必須返回一個 Response<T>
,其中包含你自定義的響應物件、快取後設資料或錯誤。
如果你的協議具有非標準快取語義,你可以自己構造一個 Cache.Entry
,但大多數請求如下使用:
return Response.success(myDecodedObject,
HttpHeaderParser.parseCacheHeaders(response));
Volley 在工作執行緒中呼叫 parseNetworkResponse()
。這確保了耗時的解析操作(例如將 JPEG 解碼為 Bitmap)不會阻塞 UI 執行緒。
1.2 deliverResponse
Volley 在 parseNetworkResponse()
方法中攜帶返回的物件回到主執行緒。大多數請求在此處呼叫回撥介面,例如:
protected void deliverResponse(T response) {
listener.onResponse(response);
六、示例:GsonRequest
Gson 是一個通過反射將 Java 物件轉換為 JSON 或者將 JSON 轉換為 Java 物件的開源庫。你可以定義擁有相同 JSON 鍵欄位的 Java 物件,將類物件傳給 Gson,Gson 自動使用響應資料填充欄位。
下面是使用 Gson 解析 Volley 請求的完整實現:
public class GsonRequest<T> extends Request<T> {
private final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Listener<T> listener;
/**
* Make a GET request and return a parsed object from JSON.
*
* @param url URL of the request to make
* @param clazz Relevant class object, for Gson's reflection
* @param headers Map of request headers
*/
public GsonRequest(String url, Class<T> clazz, Map<String, String> headers,
Listener<T> listener, ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
@Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(
gson.fromJson(json, clazz),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
}
相關文章
- Android網路請求(4) 網路請求框架VolleyAndroid框架
- Volley 原始碼解析之網路請求原始碼
- 網路請求發展介紹
- Android網路請求(終) 網路請求框架RetrofitAndroid框架
- Android網路請求(3) 網路請求框架OkHttpAndroid框架HTTP
- flutter網路請求框架dio基本使用Flutter框架
- Retrofit網路框架介紹框架
- Flutter 網路請求框架封裝Flutter框架封裝
- 簡單介紹shell中的curl網路請求的實現
- MVVM框架的搭建(三)——網路請求MVVM框架
- Flutter學習(7)——網路請求框架Dio簡單使用Flutter框架
- iOS 使用Moya網路請求iOS
- css樣式說明介紹CSS
- JavaScript介紹及說明(01)JavaScript
- Volley 原始碼解析之圖片請求原始碼
- 使用retrofit進行網路請求
- Android框架之Volley與GlideAndroid框架IDE
- Cz工具集使用介紹 - 規範Git提交說明Git
- 介紹一個請求庫 — Undici
- 面試官:說說你對網路請求加密的理解?面試加密
- Qt - http網路請求與響應QTHTTP
- 【LVS】簡介與說明
- 營銷型網站設計方案介紹及說明網站
- 如何使用 Python 請求網路資源Python
- 網路請求了
- 網路請求優化之取消請求優化
- ios-APP重構之路(一) 網路請求框架iOSAPP框架
- vue(24)網路請求模組axios使用VueiOS
- 使用Retrofit+RxJava實現網路請求RxJava
- Texpad for Mac編輯器使用說明以及快捷方式介紹Mac
- python基礎學習-埠介紹說明Python
- 介紹tomcat Connector 引數優化說明Tomcat優化
- 網路資料請求
- HTTP網路請求原理HTTP
- Android網路請求(2)Android
- TCP-UDP網路除錯助手使用說明TCPUDP除錯
- Gin框架介紹及使用框架
- [Android開源框架]RxHttp使用說明Android框架HTTP