android网络框架volley学习之基本数据类

    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网络框架中的自定义的基本数据类,了解他们的结构有助于再往下深入学习此框架的逻辑处理结构。

   不对请指正,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值