其实刚开始看volley代码的时候看到这三个类也不知道有啥区别,有点懵。先来看一看Http的响应报文:
HTTP的响应报文由状态行、消息报头、空行、响应正文组成。响应报头后面会讲到,响应正文是服务器返回的资源的内容,先来看看状态行。
状态行
1、状态行格式如下:
HTTP-Version Status-Code Reason-Phrase CRLF
例:HTTP/1.1 200 OK
其中,HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回的响应状态代码;Reason-Phrase表示状态代码的文本描述。
状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:
1.100~199:指示信息,表示请求已接收,继续处理
2.200~299:请求成功,表示请求已被成功接收、理解、接受
3.300~399:重定向,要完成请求必须进行更进一步的操作
4.400~499:客户端错误,请求有语法错误或请求无法实现
5.500~599:服务器端错误,服务器未能实现合法的请求
常见的状态码如下:
1.200 OK:客户端请求成功
2.400 Bad Request:客户端请求有语法错误,不能被服务器所理解
3.401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
4.403 Forbidden:服务器收到请求,但是拒绝提供服务
5.500 Internal Server Error:服务器发生不可预期的错误
6.503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常
在volley的HurlStack通过HttpURLConnection访问网络,首先返回的是HttpResponse对象,代码如下:
if (!hasResponseBody(request.getMethod(), responseCode)) {
return new HttpResponse(responseCode, convertHeaders(connection.getHeaderFields()));
}
return new HttpResponse(responseCode, convertHeaders(connection.getHeaderFields()),
connection.getContentLength(), inputStreamFromConnection(connection));
根据请求方式和响应值来判断是否包含一个body也就是实体内容。convertHeaders()Map
/**
* Construct a new HttpResponse.
*
* @param statusCode the HTTP status code of the response
* @param headers the response headers
* @param contentLength the length of the response content. Ignored if there is no content.
* @param content an {@link InputStream} of the response content. May be null to indicate that
* the response has no content.
*/
public HttpResponse(
int statusCode, List headers, int contentLength, InputStream content) {
mStatusCode = statusCode;
mHeaders = headers;
mContentLength = contentLength;
mContent = content;
}
成员变量是什么注释说的很清楚~。将HttpResponse返回到BasicNetwork之后,根据返回状态码进行情况判断创建不同的NetworkResponse对象返回到NetworkDispatcher。
return new NetworkResponse(statusCode, responseContents, false,
SystemClock.elapsedRealtime() - requestStart, responseHeaders);
上面这种返回是响应值为200时候的。NetworkResponse有好几个重载的构造方法如下:
/**
* Creates a new network response.
* @param statusCode the HTTP status code
* @param data Response body
* @param headers Headers returned with this response, or null for none
* @param notModified True if the server returned a 304 and the data was already in cache
* @param networkTimeMs Round-trip network time to receive network response
* @deprecated see {@link #NetworkResponse(int, byte[], boolean, long, List)}. This constructor
* cannot handle server responses containing multiple headers with the same name.
* This constructor may be removed in a future release of Volley.
*/
@Deprecated
public NetworkResponse(int statusCode, byte[] data, Map headers,
boolean notModified, long networkTimeMs) {
this(statusCode, data, headers, toAllHeaderList(headers), notModified, networkTimeMs);
}
/**
* Creates a new network response.
* @param statusCode the HTTP status code
* @param data Response body
* @param notModified True if the server returned a 304 and the data was already in cache
* @param networkTimeMs Round-trip network time to receive network response
* @param allHeaders All headers returned with this response, or null for none
*/
public NetworkResponse(int statusCode, byte[] data, boolean notModified, long networkTimeMs,
List allHeaders) {
this(statusCode, data, toHeaderMap(allHeaders), allHeaders, notModified, networkTimeMs);
}
/**
* Creates a new network response.
* @param statusCode the HTTP status code
* @param data Response body
* @param headers Headers returned with this response, or null for none
* @param notModified True if the server returned a 304 and the data was already in cache
* @deprecated see {@link #NetworkResponse(int, byte[], boolean, long, List)}. This constructor
* cannot handle server responses containing multiple headers with the same name.
* This constructor may be removed in a future release of Volley.
*/
@Deprecated
public NetworkResponse(int statusCode, byte[] data, Map headers,
boolean notModified) {
this(statusCode, data, headers, notModified, 0);
}
/**
* Creates a new network response for an OK response with no headers.
* @param data Response body
*/
public NetworkResponse(byte[] data) {
this(HttpURLConnection.HTTP_OK, data, false, 0, Collections.emptyList());
}
/**
* Creates a new network response for an OK response.
* @param data Response body
* @param headers Headers returned with this response, or null for none
* @deprecated see {@link #NetworkResponse(int, byte[], boolean, long, List)}. This constructor
* cannot handle server responses containing multiple headers with the same name.
* This constructor may be removed in a future release of Volley.
*/
@Deprecated
public NetworkResponse(byte[] data, Map headers) {
this(HttpURLConnection.HTTP_OK, data, headers, false, 0);
}
private NetworkResponse(int statusCode, byte[] data, Map headers,
List allHeaders, boolean notModified, long networkTimeMs) {
this.statusCode = statusCode;
this.data = data;
this.headers = headers;
if (allHeaders == null) {
this.allHeaders = null;
} else {
this.allHeaders = Collections.unmodifiableList(allHeaders); //作用返回一个只读的集合
}
this.notModified = notModified;
this.networkTimeMs = networkTimeMs;
}
到NetworkResponse这里 ,已经有了响应状态,响应内容,响应头等。返回到NetworkDispatcher之后,又调用Request的parseNetworkResponse方法将NetworkResponse转化为Response>。parseNetworkResponse是一个抽象方法,StringRequest里实现如下:
@Override
protected Response parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
//将byte[]数组根据指定编码转化为String
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
//HttpHeaderParser.parseCacheHeaders(response) 根据返回值header是否缓存进行缓存。
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
通过parseNetworkResponse转化为Response对象。代码如下:
/** Parsed response, or null in the case of error. */
public final T result;
/** Cache metadata for this response, or null in the case of error. */
public final Cache.Entry cacheEntry;
/** Detailed error information if errorCode != OK
. */
public final VolleyError error;
/** Returns a successful response containing the parsed result. */
public static Response success(T result, Cache.Entry cacheEntry) {
return new Response(result, cacheEntry);
}
private Response(T result, Cache.Entry cacheEntry) {
this.result = result;
this.cacheEntry = cacheEntry;
this.error = null;
}
这样就完成了转换。