Android-网络通信框架Volley使用详解

1 Volley发送get请求:

public void getJson() {

String url = "http://"+host+":8080/web/json.jsp?username=xjs&password=123456";

mQueue.add(new JsonObjectRequest(Method.GET, url, null,

new Listener<jsonobject>() {

@Override

public void onResponse(JSONObject response) {

Log.e(TAG, "response : " + response.toString());

}

}, new Response.ErrorListener() {

@Override

public void onErrorResponse(VolleyError error) {

String err = error.getMessage();

Log.e(TAG, "err : " + err);

}

}));

}

///////////////////////////////////////////////////////////////////////////////////////////

2 Volley发送post请求:

public void postJson() {

String url = "http://"+host+":8080/web/json.jsp";

StringRequest postRequest = new StringRequest(

Request.Method.POST,

url,

new Response.Listener<string>() {

@Override

public void onResponse(String response) {

// response

Log.d("Response", response);

}

}, new Response.ErrorListener() {

@Override

public void onErrorResponse(VolleyError error) {

// error

Log.d("Error.Response", error.getMessage());

}

}) {

@Override

protected Map<string, string=""> getParams() {

Map<string, string=""> params = new HashMap<string, string="">();

params.put("username", "xjs");

params.put("password", "123456");

return params;

}

};

mQueue.add(postRequest);

}

////////////////////////////////////////////////////////////////////////////////////////

3 Volley获取网络图片:

public void getImage() {

String imageUrl = "http://"+host+":8080/web/image.jsp";

NetworkImageView view = (NetworkImageView) findViewById(R.id.network_image_view);

view.setDefaultImageResId(android.R.drawable.ic_menu_rotate);

view.setErrorImageResId(android.R.drawable.ic_delete);

view.setImageUrl(imageUrl, new ImageLoader(mQueue, new BitmapLruCache(1024 * 4)));

}

////////////////////////////////////////////////////////////////////////////////////////

4 Volley发送Https请求,需要修改源码:

protected HttpURLConnection createConnection(URL url) throws IOException {

if (url.toString().toLowerCase(Locale.CHINA).startsWith("https")) {

HTTPSTrustManager.allowAllSSL();

}

return (HttpURLConnection) url.openConnection();

}

//HTTPSTrustManager.java:

public class HTTPSTrustManager implements X509TrustManager {

private static TrustManager[] trustManagers;

private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};

@Override

public void checkClientTrusted(

java.security.cert.X509Certificate[] x509Certificates, String s)

throws java.security.cert.CertificateException {

// To change body of implemented methods use File | Settings | File

// Templates.

}

@Override

public void checkServerTrusted(

java.security.cert.X509Certificate[] x509Certificates, String s)

throws java.security.cert.CertificateException {

// To change body of implemented methods use File | Settings | File

// Templates.

}

public boolean isClientTrusted(X509Certificate[] chain) {

return true;

}

public boolean isServerTrusted(X509Certificate[] chain) {

return true;

}

@Override

public X509Certificate[] getAcceptedIssuers() {

return _AcceptedIssuers;

}

public static void allowAllSSL() {

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

@Override

public boolean verify(String arg0, SSLSession arg1) {

// TODO Auto-generated method stub

return true;

}

});

SSLContext context = null;

if (trustManagers == null) {

trustManagers = new TrustManager[] { new HTTPSTrustManager() };

}

try {

context = SSLContext.getInstance("TLS");

context.init(null, trustManagers, new SecureRandom());

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

} catch (KeyManagementException e) {

e.printStackTrace();

}

HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());

}

}

////////////////////////////////////////////////////////////////////////////////////////

5 Volley获取服务端返回的cookie,需要修改源码:

@Override

public HttpResponse performRequest(Request<!--?--> request,Map<string, string=""> additionalHeaders)

throws IOException,AuthFailureError {

for (Entry<string, list<string="">> header : connection.getHeaderFields().entrySet()) {

if (header.getKey() != null) {

String key = header.getKey();

List<string> values = header.getValue();

if(key.equalsIgnoreCase("set-cookie")){

StringBuilder cookieString = new StringBuilder();

for(String value : values){

cookieString.append(value).append("\n");//用\n作为分隔符,cookie中不应该有回车符号

}

cookieString.deleteCharAt(cookieString.length() - 1);

Header h = new BasicHeader(header.getKey(), cookieString.toString());

response.addHeader(h);

}else{

Header h = new BasicHeader(header.getKey(), values.get(0));

response.addHeader(h);

}

}

}

}

//然后再request中重写parseNetworkResponse():

@Override

protected Response<string> parseNetworkResponse(NetworkResponse response) {

Response<string> superResponse = super.parseNetworkResponse(response);

Map<string, string=""> responseHeaders = response.headers;

String rawCookies = responseHeaders.get("Set-Cookie");

//服务端返回是 set-cookie:JSESSIONID=D90B58454550B4D37C4B66A76BF27B93; Path=/otn BIGipServerotn=2564030730.64545.0000; path=/

String part1 = substring(rawCookies, "", ";");

String part2 = substring(rawCookies, "\n", ";");

//客户端需要的是 cookie:JSESSIONID=D90B58454550B4D37C4B66A76BF27B93; BIGipServerotn=2564030730.64545.0000;

cookies = part1 + "; " + part2 + ";";

return superResponse;

}

////////////////////////////////////////////////////////////////////////////////////////

6 Volley发请求的时候上传cookie,在request中重写getHeaders():

@Override

public Map<string, string="">getHeaders() throws AuthFailureError {

if(cookies!= null && cookies.length() > 0){

HashMap<string,string>         headers = newHashMap<string, string="">();

headers.put("Cookie",cookies);

returnheaders;

}

returnsuper.getHeaders();

}

////////////////////////////////////////////////////////////////////////////////////////

7 Volley自定义request:

public class ByteArrayRequest extends Request<byte[]>{

private final Listener<byte[]> mListener;

public ByteArrayRequest(int method, String url, Listener<byte[]> listener, ErrorListener errlistener) {

super(method, url, errlistener);

mListener = listener;

}

@Override

protected Response<byte[]> parseNetworkResponse(NetworkResponse response) {

if(response == null){

return null;

}

if(response.statusCode != HttpStatus.SC_OK){

return null;

}

byte[] bytes = response.data;

return Response.success(bytes, null);

}

@Override

protected void deliverResponse(byte[] response) {

if(mListener != null){

mListener.onResponse(response);

}

}

}

////////////////////////////////////////////////////////////////////////////////////////

8 Volley设置请求超时时间:

@Override

public RetryPolicy getRetryPolicy() {

RetryPolicyretryPolicy = new DefaultRetryPolicy(5000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);

returnretryPolicy;

}

//////////////////////////////////////////////////////////////////////////////////////////////

附一个登陆铁道部12306的例子,源码在:http://download.csdn.net/download/goldenfish1919/7029907

Ps:我在测试的时候用了本地的一个tomcat,一块打包放在了asserts下面。

参考:

http://blog.csdn.net/xyz_lmn/article/details/12165391

http://blog.csdn.net/xyz_lmn/article/details/12746581

http://blog.csdn.net/xyz_lmn/article/details/12177005

http://www.itsalif.info/content/android-volley-tutorial-http-get-post-put

概述:http://blog.csdn.net/t12x3456/article/details/9221611

入门: http://blog.csdn.net/ttdevs/article/details/17566795

自定义request: http://blog.csdn.net/ttdevs/article/details/17586205

源码分析:http://blog.csdn.net/ttdevs/article/details/17764351

发送https请求:http://blog.csdn.net/llwdslal/article/details/18052723

构造cache:http://stackoverflow.com/questions/16682595/android-volley-imageloader-bitmaplrucache-parameter

解析服务端cookie:http://stackoverflow.com/questions/20702178/android-volley-access-http-response-header-fields,http://blog.csdn.net/hpb21/article/details/12163371

上传cookie:http://stackoverflow.com/questions/17049473/how-to-set-custom-header-in-volley-request

设置超时:http://stackoverflow.com/questions/17094718/android-volley-timeout

http://blog.csdn.net/dacainiao007/article/details/12617747,这里关于超时时间增长的因子的说法不准确,应该是当第一次连接超时以后,第二次超时时间会变为原来的多少倍,连接超时和读取超时设置为同一个数。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

在android中基于http请求的框架很多,自己如果比较了解http请求流程,自己也可以写一个不错的框架,由于一些原因,项目中我们自己开发的框架被要求用volley替换掉了,因此我不得不对volley这个开发包进行自己的研究,以希望能够熟悉整个流程,以及能够顺利的将这个开源包融入到项目中同时不会影响原有逻辑。(个人风格的原因吧,我不是很喜欢贴大段大段的代码在帖子里面,大家如果能对照volley源码来看这个帖子的话,会更有收获的)

首先啰嗦些自己对android的http请求框架的一些感悟,如果有不对的地方大家尽情拍砖拍死我吧(就算死了我也要发帖子)。

我理解的基于网络的应用最核心的其实就是request跟response的分发。这个分发机制写好了,框架够健壮,扩展性高,那么以后涉及到这个层次的改动就少(因为从一开始我们的设计都是比较初级的,会随着需求的不断增多而出现一些需要对框架机制的改动需求),因为对于分发机制的改动是很核心的,说牵一发而动全身一点也不为过,稍微改一点点都会对项目有很大的影响甚至是未知的影响,而且构建得不好的话,有些需求的改动会非常麻烦,而这些改动如果是良好的构架的话往往是可以避免的,所以,在初期能够构建好一些是很有必要的。我大概看过一些开源的项目以及这些年来自己做过的项目(没做过游戏,所以游戏的我不知道哈),感觉基于网络的应用要么用http要么用套接字,如果不需要推送的,一般都是使用http来做。

http的请求步骤大概分为这么几步,就我看来:

1)发起request,这里的发起者要是个context之类的(一般是activity或者service)东东,当然很多时候发起者也是最后数据的接受者。不同的框架对于这个发起的机制实现各不相同,但总的说来都是统一给出一个公共接口,让发起者封装好必要的信息,使用公共接口,让其实现类去启动实际的http请求操作,大概主要区别在于如何封装这些request信息。

2)进行request请求,并获取response。真正的请求和响应就在这里完成,这里可能有两个需要考虑到的,一个是线程的阻塞,有的框架会让线程阻塞直到获取到响应为止,有的框架则会在这里分发出多个线程,以避免这种阻塞,当然大多数都会采用后者了。二个就是数据的存储,有些固定的请求,比如一些不会轻易变动的信息,在第一次请求到了之后就不需要再多次请求了,一般也可以在这个部分完成这个功能。但总而言之,不管你线程分配也好,使用本地数据也好,还是你的请求出问题了也好,总之你必须在一定的时间内,给我的request一个response。

3)分派response,我们去餐馆吃饭都知道,哪桌点的菜就端到哪桌去,不能端错了。谁发出的request,最后就要给到他的接受者手里,不能给错了。有些框架是靠一些接口类的注入来保证数据的正确接受,有些框架是靠一个寻找机制来保障的(比如广播)。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

这个大牛对volley的一个感性理解:

好了,说了这么多我们来看看volley吧。前面那么多铺垫也不是白用的,我就按照我理解的这三步来拆析volley框架。

1)发起request:volley使用Request抽象类来封装请求。Request类也是整个volley项目中最核心的类(还真没有之一)。从源码我们可以看到,Request的实现类有好几种,而这些实现类有个共同的特点就是他们其实已经定义好了response返回的数据类型,也就是说,其实这里的Requst类并不单单只做request,他们也负责对response的数据处理(当然直接使用实现类的话,我们一般不管这些数据如何被处理的),我们可以自己写实现类并实现其中的数据处理方法

abstract protected Response<T> parseNetworkResponse(NetworkResponse response);

来将返回数据变成我们想要的类型,然后由我们再来进一步加工处理。

Request可不单单只做了这么一件事情。为了证明他为什么是最核心的类,我再列举几个他做了的貌似跟他不相关的事情。

abstract protected void deliverResponse(T response);

public void deliverError(VolleyError error)

有木有震惊的赶脚,是的,最后response以及error的分发的实际执行者也是Request。所以这个Request类是贯穿一个请求到响应过程自始至终的类。这个其实不难理解,最后一步的分派工作需要一定的信息来保证分派的正确性,而最能提供这些信息的,其实就是最初我们发出的request了。

简单的介绍下Request如何使用:

从源码可以看出

getUrl 是返回的 url地址,

getBody是返回的请求参数,这两个方法是在http的实际请求中肯定要用到的,使用get请求的话是需要保证getUrl的返回值正确即可,而使用post的话还要保证后面一个方法的返回值正确。

(返回值如何注入就是你们的事情了,构造函数注入也可,set 方法注入也可)

这里需要给大家注意的地方原生态的Stringrequest 没有重写 getBody 方法,也就是说 getBody 返回为null,那么 volley将默认使用get请求,如果大家想用post请求并使用Stringrequest的话,请重写这个方法。

另外还有两个很重要的类,请大家在构造request的时候务必要注入,

ErrorListener 和 Listener,一个是用来处理error(public void onErrorResponse(VolleyError error))的,一个是用来处理正常返回的(public void onResponse(T response))这两个接口的定义都在Response类中。不难想出上面我所说的两个方法abstract protected void deliverResponse(T response)和public void deliverError(VolleyError error) 的实现其实就是调用这两个接口各自的方法就可以了。

有些附加的条件我们可以酌情的考虑是否需要实现。

public String getCacheKey(),CacheKey是volley从Request获取的用于本地存储请求数据的键值,相信大家很快能明白,如果两个request的这个方法返回的值一样的话,后者将能够有机会取到前者存储在本地的数据,从而减少了网络请求。原生态的Request是使用url为cechekey,这样并不一定科学,有本地存储需求的童鞋,请切记重写此方法。当然前提是保证 public final boolean shouldCache()返回为true。否则前功尽弃。

public void setRetryPolicy(RetryPolicy retryPolicy),从字面意思就可以看出,这个是对一个request的重新请求策略的设置,不同的项目是否需要重新请求,重新请求几次,请求超时的时间,这些就在这设置到里面。一般放就是继承RetryPolicy 类,根据自己的需求实现父类方法。

不知不觉写了这么多,先写到这里吧,后面我再介绍volley如何实现第二步跟第三步。

时间: 2024-08-28 22:09:41

Android-网络通信框架Volley使用详解的相关文章

【转】Android 网络通信框架Volley简介(Google IO 2013)

Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded 1. 什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的Go

Android 网络通信框架Volley简介(Google IO 2013)

Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded 1. 什么是Volley 在 这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于 AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的

[转]Android 网络通信框架Volley简介(Google IO 2013)

Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded 1. 什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的Go

Android 网络通信框架Volley的解析

在2013年Google I/O大会上,Android开发团队公布了一个新的网络通信框架:Volley.它适合处理通信频繁的网络操作,但对于每一次通信的数据量则有较为苛刻的限制.本文将介绍该通信框架的用法(包括使用现成和自定义的Request),并从源码的角度探究其工作机制. 目前,Android系统中用于实现HTTP通信的方式主要有HttpURLConnection和HttpClient两个类[1],而封装了它们的框架主要有AsyncHttpClient和Universal-Image-Loa

Android 网络通信框架Volley简介

Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded 1. 什么是Volley Google I/O 2013上,Volley发布了volley.在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于 AsyncTaskLoader HttpURLConnection A

Android 网络通信框架Volley基本介绍

Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded 1. 什么是Volley Google I/O 2013上.Volley公布了volley.在这之前,我们在程序中须要和网络通信的时候,大体使用的东西莫过于 AsyncTaskLoader HttpURLConnection A

[转]Android-网络通信框架Volley使用详解

1 Volley发送get请求: [java] view plaincopy public void getJson() { String url = "http://"+host+":8080/web/json.jsp?username=xjs&password=123456"; mQueue.add(new JsonObjectRequest(Method.GET, url, null, new Listener<JSONObject>() 

Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送

Android高效率编码-第三方SDK详解系列(三)--JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送 很久没有更新第三方SDK这个系列了,所以更新一下这几天工作中使用到的推送,写这个系列真的很要命,你要去把他们的API文档大致的翻阅一遍,而且各种功能都实现一遍,解决各种bug各种坑,不得不说,极光推送真坑,大家使用还是要慎重,我们看一下极光推送的官网 https://www.jpush.cn/common/ 推送比较使用,很多软件有需要,所以在这个点拿出来多讲讲,我们本节

SSH框架的整合详解

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> SSH框架的整合详解 - super_YC的博客 - 博客频道 - CSDN.NET super_YC的博客 记录我生活的一点一滴!我很开心拥有这样一个自己心事的笔记本 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &nbsp [5月书讯]流畅的P