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://blog.csdn.net/t12x3456/article/details/9221611
http://blog.csdn.net/guolin_blog/article/details/17612763
http://blog.csdn.net/ttdevs/article/details/17586205