Volley的简单介绍http://blog.csdn.net/chengshuyuan_uestc/article/details/51755189
Volley源码解析(一)Volley中乱码问题及解决方案http://blog.csdn.net/chengshuyuan_uestc/article/details/51755191
Volley源码分析(二)-Volley中的Request类http://blog.csdn.net/chengshuyuan_uestc/article/details/51755197
Volley源码解析(三)网络请求流程http://blog.csdn.net/chengshuyuan_uestc/article/details/51755201
Request类和Response类
刚才我们分析了请求String发生乱码的原因与解决方案,是因为如果服务器在http响应Response中没有设定编码方式charset,就会使用默认的ISO-8859-1编码方案。更进一步,我们分析一下Request类,看一下使用Volley进行http请求的。
http请求报文分为三个部分
- 请求行 实体行包括请求的方法、请求的url地址、请求的协议版本号
- 首部行 首部行包括四个部分 主机地址、 Connection、浏览器、语言
- 实体 get方法请求时实体为空,post方法时,实体中存放请求参数
典型的HTTP请求报文:
```
GET /somedir/index.html HTTP/1.1
HOST : www.baidu.com
Connection : close
user-agent : Mozilla/5/0
Agent-language : fr
实体
```
在Volley中是怎么实现的呢?我们以StringRequest来分析
在实例化StringRequest类时,出入了参数method、url、listener、ErrorListener,在StringRequest的构造函数中直接调用了父类Request的构造函数。即在构造函数中添加了http请求报文中的url,请求方法(Request类中显示Volley有8种方法,包括GET\POST\PUT\DELETE\HEAD\OPTIONS\TRACE\PATCH)。
如果是post方法,那么参数是放在http请求保温的实体中,这些参数是怎么传入的呢?
在HrulStack类中使用HttpUrlConnection来进行http请求的时候。
1 如果请求的方法为DEPRECATED_GET_OR_POST,
byte[] postBody = request.getPostBody();
可以看到http请求内容由Request类的getPostBody()提供,我们看一下这个函数的实现。
@Deprecated
public byte[] getPostBody() throws AuthFailureError {
// Note: For compatibility with legacy clients of volley, this implementation must remain
// here instead of simply calling the getBody() function because this function must
// call getPostParams() and getPostParamsEncoding() since legacy clients would have
// overridden these two member functions for POST requests.
Map<String, String> postParams = getPostParams();
if (postParams != null && postParams.size() > 0) {
return encodeParameters(postParams, getPostParamsEncoding());
}
return null;
}
postParms是一个Map,通过getPostParams()函数得到,继续查看getPostParams()函数,getPostParms()方法只有一句,就是调用getParams(),这个函数我们好熟悉,不就是我们在进行post方法进行网络请求时需要重写的方法,在该方法中用map的方法加入参数??
在得到postParams之后,如果postParms不为空,需要encodeParameters()处理一下,以一定的格式返回。encodeParameters()函数的实现方式如下:
private byte[] encodeParameters(Map<String, String> params, String paramsEncoding) {
StringBuilder encodedParams = new StringBuilder();
try {
for (Map.Entry<String, String> entry : params.entrySet()) {
encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding));
encodedParams.append('=');
encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding));
encodedParams.append('&');
}
return encodedParams.toString().getBytes(paramsEncoding);
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
}
}
2 当然如果是GET方法的话
参数直接放在url中,就不需要这些过程了。
3 如果是POST方法呢?
如果是post方法, 则调用了ddBodyIfExists(connection, request)方法,我们看一下这个方法的实现。
//HrulStack类
private static void addBodyIfExists(HttpURLConnection connection, Request<?> request)
throws IOException, AuthFailureError {
byte[] body = request.getBody();
if (body != null) {
connection.setDoOutput(true);
connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.write(body);
out.close();
}
}
在函数内的第一行我们就看到通过调用Request类的getBody()方法来获得http请求的body。我们看一下Request类中的getBody()方法。
// Request类中
public byte[] getBody() throws AuthFailureError {
Map<String, String> params = getParams();
if (params != null && params.size() > 0) {
return encodeParameters(params, getParamsEncoding());
}
return null;
}
水落石出,同样是通过我们复写的getParams()方法后去参数后encodeParameters()方法进行转换成byte[]格式。