Volley封装,一行代码搞定http请求(重点介绍cookie、https、自定义requst请求)
来源:互联网 发布:淘宝购物车营销在哪 编辑:程序博客网 时间:2024/06/05 12:43
转载请注明出处:http://blog.csdn.net/ganklun/article/details/43372355
Google 于 2013 I/O上,发布了Volley。Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮。Volley适合数据量不大但是通信频繁的场景。本篇文章将主要介绍volley的基本用法,以及经过封装修改后,实现一行代码搞定StringRequst、JsonObjectRequest、自定义Request的http请求,同时将介绍Volley如何对Cookie以及https的支持。下面就由本屌一步一步带大家领略volley的风采吧。
1、初始化Volley队列
首先,我们需要创建一个volley队列,也就是一个RequestQueue对象。RequestQueue内部的设计就是非常合适高并发的,因此我们不必为每一次HTTP请求都创建一个RequestQueue对象,这是非常浪费资源的,基本上在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了。这里我们使用单例模式,由于本屌比较懒,所以当然使用懒汉模型啦,O(∩_∩)O哈哈~开个玩笑。代码如下所示:
private static RequestQueue getInstance(Context context) {if (requestQueue == null) {synchronized (VolleyUtil.class) {//这里的VolleyUtil.class就是我们封装好后的类。if (requestQueue == null) {requestQueue = Volley.newRequestQueue(context);requestQueue.start();}}}return requestQueue;}
2、添加Request请求对象到队列
事实上,这是第三个步骤了。实际情况是先产生request对象,然后将其加入队列。代码如下所示:
private static <T> void addRequest(RequestQueue requestQueue,Request<T> request, Object tag) {if (tag != null) {request.setTag(tag);}request.setShouldCache(false);request.setRetryPolicy(new DefaultRetryPolicy(TIME_OUT,DefaultRetryPolicy.DEFAULT_MAX_RETRIES,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));requestQueue.add(request);}
上面方法第一个参数就是我们第一步中产生的RequestQueue队列,第二个参数就是接下来我们将要介绍的各种Request对象,第三个参数则是每一个Request
对象的标识,这个标识有什么作用,大家别急,过会也会提到。该方法就做了四件事,第一设置标识,第二设置是否缓存,第三设置超时情况,第四将Request
对象添加到RequestQueue队列。
3、实例化Request对象
一、StringRequest
由于传参方式的不同,这里会将StringRequest对象的情况分为POST与GET两种情况。先看POST,代码如下所示:
public static <T> void sendStringRequestByPost(Context context, String url,Object tag, final Map<String, String> params, final Class<T> clazz,final HttpBackListener<T> listener, final boolean isLogin,final String cookieValue) {StringRequest stringRequest = new StringRequest(Method.POST, url,new Response.Listener<String>() {@Overridepublic void onResponse(String s) {T t = JSON.parseObject(s, clazz);listener.onSuccess(t);}}, new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError volleyError) {if (volleyError != null) {Log.e("VolleyError", volleyError.getMessage());listener.onFail(volleyError.networkResponse.statusCode);}}}) {@Overridepublic Map<String, String> getHeaders() throws AuthFailureError {Map<String, String> headers = new HashMap<String, String>();if (!isLogin) {headers.put(GlobConstant.COOKIE,cookieValue);return headers;}return super.getHeaders();}@Overrideprotected Map<String, String> getParams() throws AuthFailureError {return params == null ? super.getParams() : params;}};addRequest(getInstance(context), stringRequest, tag);}
该方法第一个参数不多说应用上下文,第二个参数就是你请求的httpUrl地址,第三个参数就是该request对象的tag标识,第四个参数就是我们需要提供的键值对参数,这里
是个Map<String,String>类型,第五个参数就是我们自定义的model类(解析完获取json后需要转化的实体类),第六个参数则是我们自定义的接口回调,用于处理调用成功
或者失败的情形,第七个参数其实是应用层面的参数,因为Android应用通常是在登录的时候去获取最新的header里的Cookie值,登录后为了维持与后台的会话连接,
需将最新的cookie值添加到请求头里,故重写getHeaders()方法,大家也可以根据自己的需要重写该方法。第八个参数就是我们添加的cookie值。接下来我们关注下重写
的getParams()方法,经过本屌测试该方法对于GET请求并不能讲参数顺利地提交到后台,POST请求没有问题,特此说明下,大家也可以去验证下是不是这样,欢迎前来
拍砖,(*^__^*) 嘻嘻……
接下来直接看GET请求的情况,代码如下所示:
public static <T> void sendStringRequestByGet(Context context, final String url, Object tag, final Map<String, String> params, final Class<T> clazz, final HttpBackListener<T> listener, final boolean isLogin, final String cookieValue) { StringRequest stringRequest = new StringRequest(Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String s) { T t = JSON.parseObject(s, clazz); listener.onSuccess(t); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { if (volleyError != null) { Log.e("VolleyError", volleyError.getMessage()); listener.onFail(volleyError.networkResponse.statusCode); } } }) { @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> headers = new HashMap<String, String>(); if (!isLogin) { headers.put(GlobConstant.COOKIE, cookieValue); return headers; } return super.getHeaders(); } @Override public String getUrl() { String sParams = BaseUtil.mapToStringParams(params); if (sParams.equals("")) { return super.getUrl(); } else { return url + "?" + sParams; } } }; addRequest(getInstance(context), stringRequest, tag); }
上面方法与POST的情况并没有太大区别,不同的是我们不再以重写getParams()的方式提交Map<String,String>键值对参数,而是重写getUrl()方法将params转化成paramKey1=paramValue1¶mKey2=paramValue2...的形式。
二、JsonObjectRequest
JsonObjectRequest,顾名思义传递json咯, 直接上代码:
public static <T> void sendJsonObject(Context context, int method,String url, JSONObject jsonRequest, Object tag,final Class<T> clazz, final HttpBackListener<T> listener,final boolean isLogin, final String cookieValue) {JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(method,url, jsonRequest, new Response.Listener<JSONObject>() {@Overridepublic void onResponse(JSONObject jsonObject) {T t = JSON.parseObject(jsonObject.toString(), clazz);listener.onSuccess(t);}}, new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError volleyError) {if (volleyError != null) {Log.e("VolleyError", volleyError.getMessage());listener.onFail(volleyError.networkResponse.statusCode);}}}) {@Overridepublic Map<String, String> getHeaders() throws AuthFailureError {Map<String, String> headers = new HashMap<String, String>();if (!isLogin) {headers.put(GlobConstant.COOKIE,cookieValue);return headers;}return super.getHeaders();}};addRequest(getInstance(context), jsonObjectRequest, tag);}
这里我们需要传递JsonObject对象格式的参数,响应后public void onResponse(JSONObject jsonObject)得到的也是一个JsonObject对象,该类型就是Android自带的org.json包下的。
三、自定义Request
这里依然是传递json的情况,与上面JsonObjectRequest不同的是,这里我们重写Request,事实上,在volley里Request是所有类型的Request的最顶层父类,包括上面介绍的StringRequest,JsonObjectRequest。所以不难想象,我们自定义Request也难逃其中,自定义一个JsonRequest 去继承 Request类。代码如下:
public class JsonRequest<T> extends Request<T> { private static final String PROTOCOL_CHARSET = "utf-8"; private static final String PROTOCOL_CONTENT_TYPE = String.format("application/json; charset=%s", PROTOCOL_CHARSET); private String jsonStr; private Class<T> clazz; private boolean isLogin; private Listener<T> listener; private String cookieValue; public JsonRequest(int method, String url, String jsonStr, Class<T> clazz, boolean isLogin, String cookieValue, Listener<T> listener, ErrorListener errorListener) { super(method, url, errorListener); this.jsonStr = jsonStr; this.clazz = clazz; this.isLogin = isLogin; this.cookieValue = cookieValue; this.listener = listener; } @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> headers = new HashMap<String, String>(); if (!isLogin) { headers.put(GlobConstant.COOKIE,cookieValue); return headers; } return super.getHeaders(); } @Override protected void deliverResponse(T t) { listener.onResponse(t); } @Override public String getBodyContentType() { return PROTOCOL_CONTENT_TYPE; } @Override public byte[] getBody() throws AuthFailureError { return jsonStr == null ? super.getBody() : jsonStr.getBytes(); } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { if (isLogin) { //解析请求返回的响应头 Header[] headers = response.apacheHeaders; if (headers != null) { for (Header header : headers) { if (header.getName().equalsIgnoreCase(GlobConstant.SET_COOKIE)) { //这里大家可以自由发挥,去解析自己需要的cookie. } } } } String json = new String(response.data, PROTOCOL_CHARSET); return Response.success(JSON.parseObject(json, clazz), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } }}
首先,我们重写getBodyContentType()方法来说明我们传递的媒体类型,是application/json,字符编码是UTF-8,然后我们重写了getBody()方法,注意上面的jsonStr即将你自定义的Model类(比如User类)用fastJson或者Gson转成的json字符串。然后我们重点关注 parseNetworkResponse(NetworkResponse response)这个方法,这里可以通过response.apacheHeaders获取所有的响应头,然后根据自己的需要去解析相应的cookie。最后利用Json解析工具类将Json串映射成我们自定义的实体类T。这里我用的是fastJson。至于请求头的处理和之前的情况一样,这里不再赘述。自定义好了request后,发送原理就和上面的一样了,代码如下:
public static <T> void sendJsonRequest(Context context, int method,String url, String jsonStr, Object tag, Class<T> clazz,final HttpBackListener<T> listener, final boolean isLogin,final String cookieValue) {JsonRequest<T> jsonRequest = new JsonRequest<T>(method, url, jsonStr,clazz, isLogin, cookieValue, new Listener<T>() {@Overridepublic void onResponse(T t) {listener.onSuccess(t);}}, new ErrorListener() {@Overridepublic void onErrorResponse(VolleyError volleyError) {if (volleyError != null) {Log.e("VolleyError", volleyError.getMessage());listener.onFail(volleyError.networkResponse.statusCode);}}});addRequest(getInstance(context), jsonRequest, tag);}
是不是和上面的情况很像呀,对,其实就是这样,这里我们调用我们自定义的Request。
4、取消Request请求
Activity被终止之后,如果继续使用其中的Context,除了没必要的浪费CPU,电池,网络等资源,有可能还会导致程序crash,所以,我们要防止这种情况的发生。
使用volley,我们可以在Activity停止的时候,同时取消所有或部分未完成的网络请求。代码如下:
public static void cancelAllByTag(Object tag) {if (null != requestQueue) {if (tag != null) {requestQueue.cancelAll(tag);}}}public static void cancelAll(Context context) {if (null != requestQueue) {requestQueue.cancelAll(context);}}
你可以在Activity的onStop方法里调用以上两个方法。Volley里所有的请求结果会返回给主线程,如果在主线程里取消了某些请求,则这些请求将不会被返回给主线程。
5、支持https
对于https的支持,大家可以参考这篇文章http://blog.csdn.net/llwdslal/article/details/18052723。本屌已经将其方法编译到最新的jar包里,大家无须编写任何代码。直接使用即可。
6、代码下载
https://github.com/GankLun/VolleyUtils。
7、总结
Volley在性能方面进行了大幅度的调整,它的适用场景就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。本来还想写一点关于volley网络图片加载的东东,说了本人比较懒,第一次写这样的技术博客,哎。。。还是留到下一次写吧。最后,大家是不是可以考虑在今后的网络程序编写中引入volley了呢?
- Volley封装,一行代码搞定http请求(重点介绍cookie、https、自定义requst请求)
- 自定义封装Volley的请求集合
- Volley的Https请求
- Volley的Https请求
- Volley支持https请求
- 封装UniversalImageLoader框架实现一行代码即可加载图片,且完美支持https图片请求
- Android中原http请求的https实现(URLConnection 、volley)(volley不修改源码)
- Android中原http请求的https实现(URLConnection 、volley)(volley不修改源码)
- Volley请求封装
- Volley请求封装
- Volley自定义请求
- Volley框架支持HTTPS请求。
- Volley框架支持HTTPS请求
- Volley框架支持HTTPS请求。
- iOS一行代码搞定网络请求(AFNetWorking结合ReactiveCocoa)(3)
- java代码中http请求与https请求
- 封装Volley使Volley的每个请求都自动保存和发送Cookie
- 用Requst获取请求数据
- android 对代码混淆
- POJ 3377 Ferry Lanes
- 总结iOS 8和Xcode 6的各种坑
- 译自five popular myths about c++ --by Bjarne Stroustrup (3)
- stringstream对象的使用
- Volley封装,一行代码搞定http请求(重点介绍cookie、https、自定义requst请求)
- oracle扩展表空间
- 企业开发
- Leetcode -- Maximal Rectangle
- android开发之高仿中国建设银行App
- eclipse安装ajdt插件后:java.lang.NoClassDefFoundError: test/HelloWord
- VS回写Teamcity版本号
- 高手是有理由的
- 支付宝 ALI129 错误