Volley(五)—— 自定义Request
详细解读Volley(四)—— 自定义Request
Volley中提供了几个Request,如果我们有特殊的需求,完全可以自定义Request的,自定义Request自然要继承Request,那么本篇就教大家来一步一步地定义一个自己的Request类。
一、继承Request
如果我们的request的对象不是string,也不是JsonObject,而是一个奇怪的对象呢?我这里建立了一个类,叫做:Kale,然后定义了一个CustomReqeust去继承Reqeust,得到如下的代码。
package com.kale.volleytest;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
public class CustomReqeust extends Request<Kale>{
public CustomReqeust(int method, String url, ErrorListener listener) {
super(method, url, listener);
}
@Override
protected Response<Kale> parseNetworkResponse(NetworkResponse response) {
// TODO 自动生成的方法存根
return null;
}
@Override
protected void deliverResponse(Kale response) {
// TODO 自动生成的方法存根
}
}
分析:
public CustomReqeust(int method, String url, ErrorListener listener)
构造函数中调用了父类的方法,初始化了当前对象。传入三个参数:①请求方式,即POST/GET,②请求的URL,③出错时的回调监听器
protected Response<Kale> parseNetworkResponse(NetworkResponse response)
解析网络响应的结果,从NetworkResponse的代码中我们就可以知道它里面有什么东西了。
/**
* Data and headers returned from {@link Network#performRequest(Request)}.
*/
public class NetworkResponse {
/**
* Creates a new network response.
* @param statusCode the HTTP status code
* @param data Response body
* @param headers Headers returned with this response, or null for none
* @param notModified True if the server returned a 304 and the data was already in cache
* @param networkTimeMs Round-trip network time to receive network response
*/
public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers,
boolean notModified, long networkTimeMs)
响应码啊,请求头什么的,最最主要的就是这个比特数组的data,响应的结果就在里面。我们可以自由的进行处理了~
protected void deliverResponse(Kale response)
分发响应的结果,我们可以通过将这个response放到监听器里来获取响应结果。
二、分析StringRequest
我们现在已经对request的子类有了基本的认识,现在就来看看StringRequest的源码吧,别担心,很短!
package com.android.volley.toolbox;public class StringRequest extends Request<String> {
// 建立监听器来获得响应成功时返回的结果
private final Listener<String> mListener;
// 传入请求方法,url,成功时的监听器,失败时的监听器
public StringRequest(int method, String url, Listener<String> listener,
ErrorListener errorListener) {
super(method, url, errorListener);
// 初始化成功时的监听器
mListener = listener;
}
/**
* Creates a new GET request.
* 建立一个默认的GET请求,调用了上面的构造函数
*/
public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) {
this(Method.GET, url, listener, errorListener);
}
@Override
protected void deliverResponse(String response) {
// 用监听器的方法来传递下响应的结果
mListener.onResponse(response);
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
// 调用了new String(byte[] data, String charsetName) 这个构造函数来构建String对象,
// 将byte数组按照特定的编码方式转换为String对象
// 主要部分是data
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
}
分析完代码我们应该就能知道改如何自定义Request了,其实没啥高深的东西。
三、自定义XMLRequest
代码来自:http://blog.csdn.net/guolin_blog/article/details/17612763
public class XMLRequest extends Request<XmlPullParser> {
private final Listener<XmlPullParser> mListener;
public XMLRequest(int method, String url, Listener<XmlPullParser> listener,
ErrorListener errorListener) {
super(method, url, errorListener);
mListener = listener;
}
public XMLRequest(String url, Listener<XmlPullParser> listener, ErrorListener errorListener) {
this(Method.GET, url, listener, errorListener);
}
@Override
protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse response) {
try {
String xmlString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(xmlString));
return Response.success(xmlPullParser, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (XmlPullParserException e) {
return Response.error(new ParseError(e));
}
}
@Override
protected void deliverResponse(XmlPullParser response) {
mListener.onResponse(response);
}
}
这里用到了XmlPull的知识,如果不是很了解,可以去这篇文章看看:http://www.cnblogs.com/tianzhijiexian/p/4020250.html
测试代码:
XMLRequest xmlRequest = new XMLRequest(
"http://flash.weather.com.cn/wmaps/xml/china.xml",
new Response.Listener<XmlPullParser>() {
@Override
public void onResponse(XmlPullParser response) {
try {
int eventType = response.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG:
String nodeName = response.getName();
if ("city".equals(nodeName)) {
String pName = response.getAttributeValue(0);
Log.d("TAG", "pName is " + pName);
}
break;
}
eventType = response.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("TAG", error.getMessage(), error);
}
});
mQueue.add(xmlRequest);
结果:
四、自定义GsonRequest
代码来自:http://blog.csdn.net/guolin_blog/article/details/17612763
public class GsonRequest<T> extends Request<T> {
private final Listener<T> mListener;
private Gson mGson;
private Class<T> mClass;
public GsonRequest(int method, String url, Class<T> clazz, Listener<T> listener,
ErrorListener errorListener) {
super(method, url, errorListener);
mGson = new Gson();
mClass = clazz;
mListener = listener;
}
public GsonRequest(String url, Class<T> clazz, Listener<T> listener,
ErrorListener errorListener) {
this(Method.GET, url, clazz, listener, errorListener);
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(mGson.fromJson(jsonString, mClass),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
@Override
protected void deliverResponse(T response) {
mListener.onResponse(response);
}
}
代码十分简单,先是将服务器响应的数据解析出来,然后通过调用Gson的fromJson方法将数据组装成对象。在deliverResponse方法中仍然是将最终的数据进行回调。
用法:
建立一个对象类,比如这里的weather、WeatherInfo类,然后初始化GsonRequest对象,最后把GsonRequest对象添加到队列中。
Weather:
public class Weather { private WeatherInfo weatherinfo; public WeatherInfo getWeatherinfo() { return weatherinfo; } public void setWeatherinfo(WeatherInfo weatherinfo) { this.weatherinfo = weatherinfo; } }
WeatherInfo:
public class WeatherInfo { private String city; private String temp; private String time; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getTemp() { return temp; } public void setTemp(String temp) { this.temp = temp; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } }
Java测试代码:
GsonRequest<Weather> gsonRequest = new GsonRequest<Weather>(
"http://www.weather.com.cn/data/sk/101010100.html", Weather.class,
new Response.Listener<Weather>() {
@Override
public void onResponse(Weather weather) {
WeatherInfo weatherInfo = weather.getWeatherinfo();
Log.d("TAG", "city is " + weatherInfo.getCity());
Log.d("TAG", "temp is " + weatherInfo.getTemp());
Log.d("TAG", "time is " + weatherInfo.getTime());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("TAG", error.getMessage(), error);
}
});
mQueue.add(gsonRequest);
五、重写getBody()方法来添加post参数
我们可以在JsonRequest类中发现如下代码:
/**
* Returns the raw POST or PUT body to be sent.
*
* @throws AuthFailureError in the event of auth failure
*/
@Override
public byte[] getBody() {
try {
return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
mRequestBody, PROTOCOL_CHARSET);
return null;
}
}
不用看代码,直接看注释,说明这里执行post请求,所以我们可以在这里设置post参数。这里
return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);
返回的就是post参数了。
如果我们想要传递POST数据,可以参考上面的代码,重写Request的getBody()方法,放入自己的参数,举例如下:
/** http请求编码方式 */
private static final String PROTOCOL_CHARSET = "utf-8";
private String mUserName;
@Override
public byte[] getBody() {
try {
return mUserName == null ? null : mUserName.getBytes(PROTOCOL_CHARSET);
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mUserName, PROTOCOL_CHARSET);
return null;
}
}
完整代码(来自:http://blog.csdn.net/ttdevs/article/details/17586205):
public class CustomReqeust extends Request<String> {
/** http请求编码方式 */
private static final String PROTOCOL_CHARSET = "utf-8";
private Listener<String> mListener;
private String mUserName;
public CustomReqeust(String url, String userName, Listener<String> listener, ErrorListener errorListener) {
super(Method.POST, url, errorListener);
mUserName = userName;
mListener = listener;
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
@Override
public byte[] getBody() {
try {
return mUserName == null ? null : mUserName.getBytes(PROTOCOL_CHARSET);
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mUserName, PROTOCOL_CHARSET);
return null;
}
}
}
测试代码:
private void customRequest() {
CustomReqeust request = new CustomReqeust(URL, "CustomVolley", new Listener<String>() {
@Override
public void onResponse(String arg0) {
Toast.makeText(getApplicationContext(), arg0, Toast.LENGTH_LONG).show();
Log.d("onResponse", arg0);
}
}, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
Toast.makeText(getApplicationContext(), arg0.toString(), Toast.LENGTH_LONG).show();
Log.d("onErrorResponse", arg0.toString());
}
});
mQueue.add(request);
}
抓包结果:
得到了传递的username = CustomVolley
作者: 一点点征服
出处:http://www.cnblogs.com/ldq2016/
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利