详细解读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);

结果:

详细解读Volley(四)—— 自定义Request

四、自定义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);
}

抓包结果:

详细解读Volley(四)—— 自定义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

上一篇:Kafka消息序列化和反序列化


下一篇:利用人工智能(Magpie开源库)给一段中文的文本内容进行分类打标签