編寫:kesenhoo - 原文:http://developer.android.com/training/volley/request-custom.html
這節(jié)課會(huì)介紹如何實(shí)現(xiàn)自定義的請(qǐng)求類型,這些自定義的類型不屬于 Volley 內(nèi)置支持包里面。
大多數(shù)的請(qǐng)求類型都已經(jīng)包含在 Volley 的工具箱里面。如果我們的請(qǐng)求返回?cái)?shù)值是一個(gè) string,image 或者 JSON,那么是不需要自己去實(shí)現(xiàn)請(qǐng)求類的。
對(duì)于那些需要自定義的請(qǐng)求類型,我們需要執(zhí)行以下操作:
Request<T>
類,<T>
表示解析過(guò)的響應(yīng)請(qǐng)求預(yù)期的數(shù)據(jù)類型。因此如果我們需要解析的響應(yīng)類型是一個(gè) String,可以通過(guò)繼承 Request<String>
來(lái)創(chuàng)建自定義的請(qǐng)求。請(qǐng)參考 Volley 工具類中的 StringRequest
與 ImageRequest
來(lái)學(xué)習(xí)如何繼承 Request<T>
。parseNetworkResponse()
與 deliverResponse()
,下面會(huì)詳細(xì)介紹。一個(gè) Response
封裝了用于發(fā)送的給定類型(例如,string、image、JSON等)解析過(guò)的響應(yīng)。下面會(huì)演示如何實(shí)現(xiàn) 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
...
}
請(qǐng)注意:
parseNetworkResponse()
的參數(shù)是類型是 NetworkResponse
,這種參數(shù)以 byte[]、HTTP status code 以及 response headers 的形式包含響應(yīng)負(fù)載。Response<T>
,它包含了我們指定類型的響應(yīng)對(duì)象與緩存 metadata 或者是一個(gè)錯(cuò)誤。如果我們的協(xié)議沒(méi)有標(biāo)準(zhǔn)的緩存機(jī)制,那么我們可以自己建立一個(gè) Cache.Entry
, 但是大多數(shù)請(qǐng)求都可以用下面的方式來(lái)處理:
return Response.success(myDecodedObject,
HttpHeaderParser.parseCacheHeaders(response));
Volley 在工作線程中執(zhí)行 parseNetworkResponse()
方法。這確保了耗時(shí)的解析操作,例如 decode 一張 JPEG 圖片成 bitmap,不會(huì)阻塞 UI 線程。
Volley 會(huì)把 parseNetworkResponse()
方法返回的數(shù)據(jù)帶到主線程的回調(diào)中。如下所示:
protected void deliverResponse(T response) {
listener.onResponse(response);
Gson 是一個(gè)使用映射支持 JSON 與 Java 對(duì)象之間相互轉(zhuǎn)換的庫(kù)文件。我們可以定義與 JSON keys 相對(duì)應(yīng)名稱的 Java 對(duì)象。把對(duì)象傳遞給 Gson,然后 Gson 會(huì)幫我們?yōu)閷?duì)象填充字段值。下面是一個(gè)完整的示例:演示了使用 Gson 解析 Volley 數(shù)據(jù):
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));
}
}
}
如果你愿意使用的話,Volley 提供了現(xiàn)成的 JsonArrayRequest
與 JsonArrayObject
類。參考上一課創(chuàng)建標(biāo)準(zhǔn)的網(wǎng)絡(luò)請(qǐng)求。