Android HTTP网络通信(三):Volley框架——定制Request
2015-03-18 16:19
495 查看
上一篇文章我们已经掌握了Volley各种Request的使用方法,包括StringRequest、JsonRequest、ImageRequest等。其中StringRequest用于请求一条普通的文本数据,JsonRequest(JsonObjectRequest、JsonArrayRequest)用于请求一条JSON格式的数据,ImageRequest则是用于请求网络上的一张图片。
我们都知道,在网络上传输的数据通常有两种格式,JSON和XML,那么如果想要请求一条XML格式的数据该怎么办呢?其实很简单,Volley提供了非常强的扩展机制,使得我们可以很轻松地定制出任意类型的Request。
首先查看StringRequest的源码,如下代码:
首先StringRequest继承自Request类,Request可以指定一个泛型类,这里指定是String,接下来StringRequest中提供了两个有参的构造函数,参数包括请求类型,请求地址,以及响应回调等,由于我们已经很熟悉StringRequest的用法了,相信这几个参数的作用都不用再解释了吧。但需要注意的是,在构造函数中一定要调用super()方法将这几个参数传给父类,因为HTTP的请求和响应都是在父类中自动处理的。
另外,由于Request类中的deliverResponse()和parseNetworkResponse()是两个抽象方法,因此StringRequest中需要对这两个方法进行实现。deliverResponse()方法中的实现很简单,仅仅是调用了mListener中的onResponse()方法,并将response内容传入即可,这样就可以将服务器响应的数据进行回调了。parseNetworkResponse()方法中则应该对服务器响应的数据进行解析,其中数据是以字节的形式存放在NetworkResponse的data变量中的,这里将数据取出然后组装成一个String,并传入Response的success()方法中即可。
了解了StringRequest的实现原理,下面我们就可以动手来尝试实现一下XMLRequest了,代码如下:
可以看到,基本都是仿照StringRequest写下来的,XMLRequest也是继承自Request类的,只不过这里指定的泛型类是XmlPullParser,说明我们准备使用Pull解析的方式来解析XML。在parseNetworkResponse()方法中,先是将服务器响应的数据解析成一个字符串,然后设置到XmlPullParser对象中,在deliverResponse()方法中则是将XmlPullParser对象进行回调。
在代码中按照以下的方式来使用XMLRequest,如下代码:
先创建出一个XMLRequest实例,并把服务器接口地址传入,然后在onResponse()方法中解析响应的XML数据,并把每个省的名字打印出来,最后将这个XMLRequest添加到RequestQueue当中。
运行代码,观察控制台日志,就可以看到每个省的名字都从XML中解析出来了,如下图所示:
下载地址:http://download.csdn.net/detail/dengchenhe/8512021
定义一个GsonRequest继承自Request,代码如下:
可以看到,GsonRequest是继承自Request类的,并且同样提供了两个构造函数。在parseNetworkResponse()方法中,先是将服务器响应的数据解析出来,然后通过调用Gson的fromJson方法将数据组装成对象。在deliverResponse方法中仍然是将最终的数据进行回调。
接下来使用对象的方式将这段JSON字符串表示出来。新建一个Weather类,代码如下:
Weather类中只是引用了WeatherInfo这个类。接着新建WeatherInfo类,代码如下:
下面就调用GsonRequest,代码如下:
可以看到,这里onResponse()方法的回调中直接返回了一个Weather对象,我们通过它就可以得到WeatherInfo对象,接着就能从中取出JSON中的相关数据了。运行代码,观察控制台日志,打印数据如下图所示:
我们都知道,在网络上传输的数据通常有两种格式,JSON和XML,那么如果想要请求一条XML格式的数据该怎么办呢?其实很简单,Volley提供了非常强的扩展机制,使得我们可以很轻松地定制出任意类型的Request。
自定义XMLRequest
参考一下Volley的源码,查看StringRequest是怎么实现的,然后就可以模仿着写出XMLRequest了。首先查看StringRequest的源码,如下代码:
public class StringRequest extends Request<String> { private final Listener<String> mListener; /** * Creates a new request with the given method. * * @param method the request {@link Method} to use * @param url URL to fetch the string at * @param listener Listener to receive the String response * @param errorListener Error listener, or null to ignore errors */ public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; } /** * Creates a new GET request. * * @param url URL to fetch the string at * @param listener Listener to receive the String response * @param errorListener Error listener, or null to ignore errors */ 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 { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); } }
首先StringRequest继承自Request类,Request可以指定一个泛型类,这里指定是String,接下来StringRequest中提供了两个有参的构造函数,参数包括请求类型,请求地址,以及响应回调等,由于我们已经很熟悉StringRequest的用法了,相信这几个参数的作用都不用再解释了吧。但需要注意的是,在构造函数中一定要调用super()方法将这几个参数传给父类,因为HTTP的请求和响应都是在父类中自动处理的。
另外,由于Request类中的deliverResponse()和parseNetworkResponse()是两个抽象方法,因此StringRequest中需要对这两个方法进行实现。deliverResponse()方法中的实现很简单,仅仅是调用了mListener中的onResponse()方法,并将response内容传入即可,这样就可以将服务器响应的数据进行回调了。parseNetworkResponse()方法中则应该对服务器响应的数据进行解析,其中数据是以字节的形式存放在NetworkResponse的data变量中的,这里将数据取出然后组装成一个String,并传入Response的success()方法中即可。
了解了StringRequest的实现原理,下面我们就可以动手来尝试实现一下XMLRequest了,代码如下:
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); } }
可以看到,基本都是仿照StringRequest写下来的,XMLRequest也是继承自Request类的,只不过这里指定的泛型类是XmlPullParser,说明我们准备使用Pull解析的方式来解析XML。在parseNetworkResponse()方法中,先是将服务器响应的数据解析成一个字符串,然后设置到XmlPullParser对象中,在deliverResponse()方法中则是将XmlPullParser对象进行回调。
在代码中按照以下的方式来使用XMLRequest,如下代码:
private void testVolleyXMLRequest(Context context) { RequestQueue mQueue = Volley.newRequestQueue(context); XMLRequest stringRequest = 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(stringRequest); }
先创建出一个XMLRequest实例,并把服务器接口地址传入,然后在onResponse()方法中解析响应的XML数据,并把每个省的名字打印出来,最后将这个XMLRequest添加到RequestQueue当中。
运行代码,观察控制台日志,就可以看到每个省的名字都从XML中解析出来了,如下图所示:
自定义GsonRequest
首先需要把gson的jar包添加到项目当中下载地址:http://download.csdn.net/detail/dengchenhe/8512021
定义一个GsonRequest继承自Request,代码如下:
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> class1, Listener<T> listener, ErrorListener errorListener) { super(method, url, errorListener); mGson = new Gson(); mClass = class1; 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); } }
可以看到,GsonRequest是继承自Request类的,并且同样提供了两个构造函数。在parseNetworkResponse()方法中,先是将服务器响应的数据解析出来,然后通过调用Gson的fromJson方法将数据组装成对象。在deliverResponse方法中仍然是将最终的数据进行回调。
接下来使用对象的方式将这段JSON字符串表示出来。新建一个Weather类,代码如下:
public class Weather { private WeatherInfo weatherinfo; public WeatherInfo getWeatherinfo() { return weatherinfo; } public void setWeatherinfo(WeatherInfo weatherinfo) { this.weatherinfo = weatherinfo; } }
Weather类中只是引用了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; } }
下面就调用GsonRequest,代码如下:
private void testVolleyGSONRequest(Context context) { RequestQueue mQueue = Volley.newRequestQueue(context); GsonRequest<Weather> gsonRequest = new GsonRequest<Weather>("http://www.weather.com.cn/adat/sk/101200101.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); }
可以看到,这里onResponse()方法的回调中直接返回了一个Weather对象,我们通过它就可以得到WeatherInfo对象,接着就能从中取出JSON中的相关数据了。运行代码,观察控制台日志,打印数据如下图所示:
相关文章推荐
- Android HTTP网络通信(二):Volley框架——介绍、基本用法
- Android-Volley网络通信框架(自定义Request 请求:实现 GsonRequest)
- Android-Volley网络通信框架(StringRequest和JsonObjectRequset)
- Android-Volley网络通信框架(StringRequest & JsonObjectRequest)
- Android网络通信框架Volley——自定义Request(Get、Post、文件上传)
- Android 网络通信框架Volley简介(Google IO 2013)(转载自http://blog.csdn.net/t12x3456/article/details/9221611)
- Android 网络通信框架Volley的简单使用
- Android 网络通信框架Volley(三)
- Android 网络通信框架Volley简介(Google IO 2013)
- Android 网络通信框架Volley简介以及获取JSON对象和图片加载例子
- Android轻网络通信框架--Volley
- Android网络通信框架:Volley
- Android 网络通信框架Volley简介(Google IO 2013)
- Android 网络通信框架Volley简介(Google IO 2013)
- Android网络通信框架Volley初体验
- Android 网络通信框架Volley简介(Google IO 2013)
- [Android开发常见问题-20] Android 网络通信框架Volley简介(Google IO 2013)
- Android 网络通信框架Volley简介(Google IO 2013)
- Android 网络通信框架Volley简介(Google IO 2013)
- Android 网络通信框架Volley简介(Google IO 2013)