volley网络框架中并没有直接采用android中已有的请求类和响应类,而是自己定义了这些类,将请求和响应封装在自定义的类中。为了实现缓存机制,同时定义了缓存体类和缓存头类。
在介绍Request类之前,先介绍一下请求和响应的结构。请求体是客户端向服务器发出请求的数据的包装,它由请求行、请求头和请求体构成。其中请求行中包含着请求方法(一般是GET和POST)、请求路径和所使用的协议版本。整个请求的结构如下图所示:
请求消息的结构 响应消息的结构
备注:对于GET方法来说,请求体中一般为空,它的请求体一般放在请求路径中。
而响应同样由三部分构成:响应行(由协议版本、响应码和message组成)、响应头和响应体构成,结构如上图所示。
具体的请求头和响应头有如下几种:
下面逐个查看这几个基本的数据类:
Request类
public abstract class Request<T> implements Comparable<Request<T>>{ //设置参数的编码格式 private static final String DEFAULT_PARAMS_ENCODING = "utf-8"; //定义方法接口 public interface Methods{ int DEFAULT_GET_OR_POST = -1; int GET = 0; int POST = 1; int PUT = 2; int DELETE = 3; } //访问的网络地址 private final String mUrl; //在请求队列中的位置 private Integer mSequeue; //当前请求所在的队列 private RequestQueue mRequestQueue; //当前请求是否需要缓存 private boolean mShouldCache; //当前请求是否取消 private boolean mCanceled = false; //当前请求的请求方法 private int mMethod; //标志 private Object mTag; //当前请求的 缓存体 private Cache.Entry mCacheEntry; //错误传送接口 private Response.ErrorLister<T> mErrorListener; //请求构造函数 public Request(int method,String url,Response.ErrorLister listener){ this.mMethod = method; this.mUrl = url; this.mErrorListener = listener; } //设置请求的方法 public void setMethod(int method){ this.mMethod = method; } //获取请求的方法 public int getMethod(){ return mMethod; } //设置标志 public void setTag(Object tag){ this.mTag = tag; } //获取标志 public Object getTag(){ return mTag; } //为当前请求设置它所属的请求队列 public void setRequestQueue(RequestQueue requestQueue){ this.mRequestQueue = requestQueue; } //为当前请求设置在队列中的位置 public final void setSequeue(int sequeue){ this.mSequeue = sequeue; } //获取当前请求在队列中的位置 public int getSequeue(){ return mSequeue; } //获取请求的url地址 public String getUrl(){ return mUrl; } //获取缓存的关键字 这里将url作为缓存的关键字 public String getCacheKey(){ return getUrl(); } //设置缓存体 public void setCacheEntry(Cache.Entry entry){ this.mCacheEntry = entry; } //获取存在当前请求中的缓存体 public Cache.Entry getCacheEntry(){ return mCacheEntry; } //取消当前的请求 public void cancel(){ mCanceled = true; } //判断 当前请求是否取消 public boolean isCancel(){ return mCanceled; } //设置当前请求是否需要缓存 public final void setShouldCache(boolean shoulsCache){ mShouldCache = shoulsCache; } //判断当前请求是否需要缓存 public boolean shouldCache(){ return mShouldCache; } //获取当前请求的请求头。如果网络访问时需要此信息,则重写此方法向Map中添加请求头信息。 public Map<String,String> getHeaders(){ return Collections.emptyMap(); } //获取当前请求的请求参数,请求有参数时需要重写此方法。 protected Map<String, String> getParams(){ return null; } //对于post请求获取它的请求参数, protected Map<String, String> getPostParams(){ return getParams(); } //获取post请求参数的编码格式 protected String getPostParamsEncoding(){ return getParamsEncoding(); } //获取请求参数的编码 private String getParamsEncoding() { return DEFAULT_PARAMS_ENCODING; } //获取post请求的请求内容类型 public String getPostBodyContentType(){ return getBodyContentType(); } //获取请求的请求内容类型 public String getBodyContentType() { return "application/x-www-form-urlencoded; charset="+DEFAULT_PARAMS_ENCODING; } public byte[] getBody(){ Map<String, String> params = getParams(); if(params != null && params.size()>0){ return encodeParameters(params,getParamsEncoding()); } return null; } //根据传递的编码方式将获取到的参数转换成字节数组 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 e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } //需要重写的方法 将NetworkResponse对象转化成 Response对象 abstract protected Response<T> parseNetworkResponse(NetworkResponse response); /*需要重写的方法 负责将response对象解析后传回客户端,一般情况下 自定义的request会在其构造函数中引入一个 response.Listener参数,再重写此方法时调用mListener.onResponse()方法,让response在其中被解析并传回客户端*/ abstract protected void deliverResponse(T response); //发生错误时,移交给错误监听器处理 public void deliverError(VolleyError error){ if(mErrorListener != null){ mErrorListener.onErrorResponse(error); } } public void finish(){ if(mRequestQueue != null){ mRequestQueue.finish(this); } } //为请求事件添加一个事件输出,用于调试程序 public void addMarker(String tag) { if(MarkerLog.ENABLED){ mEventLog.add(tag,Thread.currentThread().getId()); }else if(mRequestBirthTime == 0){ mRequestBirthTime = SystemClock.elapsedRealtime(); } } @Override public int compareTo(Request<T> arg0) { // TODO Auto-generated method stub return 0; } public int getTimeoutMs() { // TODO Auto-generated method stub return 0; } }
NetworkResponse类
此类为response的一个过度类,由标准的HttpResponse响应重新构造而成。由它的构造函数不然看出,这个类中封装了响应的状态码、响应体和响应头以及判断服务器对应的资源是否修改。
//属性:状态码 数据 响应头 public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers, boolean notModified) { this.statusCode = statusCode; this.data = data; this.headers = headers; this.notModified = notModified; }
Response类
response类相对简单点,它主要封装了由用户通过实现abstract protected Response<T> parseNetworkResponse( response)从networkResponse对象中将数据进行解析,转化成客户端所需要的数据格式(客户端需要图片则将数据通过文件输出流转换成图片,如果需要字符串则生成字符串)。
public static <T> Response<T> success(T result, Cache.Entry cacheEntry) { return new Response<T>(result, cacheEntry); } private Response(T result, Cache.Entry cacheEntry) { this.result = result; this.cacheEntry = cacheEntry; this.error = null; }Entry类
public class Entry { //本地缓存的响应体 public byte[] data; //标志 public String etag; //缓存的生存时间 public long ttl; //缓存的soft生存时间(不太懂) public long softTtl; //服务器做出此响应的时间 public long serverDate; //响应头 public Map<String, String> responseHeaders = Collections.emptyMap(); //是否过期 public boolean isExpired(){ return this.ttl < System.currentTimeMillis(); } //是否需要更新 public boolean refreshNeeded(){ return this.softTtl < System.currentTimeMillis(); } }
CacheHeader类
此类将entry类的数据换成数据的长度。个人觉得这个类的存在就是为了减少内存的占有,不然在DiskBasedCache类中的map集合中要添加entry类显然是内存的过度的消耗,故volley设计者设计CacheHeader类提供一个类似于索引的功能。
static class CacheHeader { //缓存的大小 public long size; //缓存头的关键字 public String key; //缓存头的标志 public String etag; public long serverDate; public long ttl; public long softTtl; public Map<String, String> responseHeaders; private CacheHeader() { } //由缓存体转换成缓存头 public CacheHeader(String key, Entry entry) { this.key = key; this.size = entry.data.length; this.etag = entry.etag; this.serverDate = entry.serverDate; this.ttl = entry.ttl; this.softTtl = entry.softTtl; this.responseHeaders = entry.responseHeaders; } //由缓存头构造缓存体 public Entry toCacheEntry(byte[] data) { Entry e = new Entry(); e.data = data; e.etag = this.etag; e.serverDate = this.serverDate; e.softTtl = this.softTtl; e.ttl = this.ttl; e.responseHeaders = this.responseHesders; return e; }
以上就是Volley网络框架中的自定义的基本数据类,了解他们的结构有助于再往下深入学习此框架的逻辑处理结构。
不对请指正,谢谢!