1 Volley发送get请求:java
public void getJson() {android
String url = "http://"+host+":8080/web/json.jsp?username=xjs&password=123456";web
mQueue.add(new JsonObjectRequest(Method.GET, url, null,json
new Listener<jsonobject>() {tomcat
@Overridecookie
public void onResponse(JSONObject response) {网络
Log.e(TAG, "response : " + response.toString());app
}框架
}, new Response.ErrorListener() {dom
@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如何实现第二步跟第三步。