Volley的框架解读七(Request)
来源:互联网 发布:软考数据库工程师 编辑:程序博客网 时间:2024/05/22 17:00
先看看UML图
Request也是volley的核心类之一,是一个抽象类。volley中所有的请求都是由Request的子类来完成的,它定义了一些公共性的内容,并抽象出来,其子类只需要继承该类并实现其预留的抽象方法即可。比如volley默认实现的请求如StringRequest、JsonRequest、JsonObjectRequest等都是继承自Request。再比如在Google的官方文档中定义的GsonRequest也是继承该类。如果有需要开发者也可以自己继承Request,定制自己的请求。扩展性极好。
OK,进入正题,接下来主要记录下自己对于Request的一些理解。
其实从字面理解Request,是请求的意思,有很长一段时间我都把它认为是一个网络请求,后来随着学习的深入,才了解到,不能把他归为一个请求,更准确的说应该是:对一个网络请求所必须的属性参数的描述。可以这么说,Request中描述了一个网络请求所需要的请求方式(post get等)、参数、编码方式、url等。
另外Request还定义了一个请求在volley中特有的属性,比如该request的序列号、是否可以被缓存、请求是否被取消了、请求的响应时间、请求的tag、数据体等
接下来看一下Request的源码:
volley支持的网络请求方式:
public interface Method { int DEPRECATED_GET_OR_POST = -1; int GET = 0; int POST = 1; int PUT = 2; int DELETE = 3; }
Request的构造方法:在创建request的时候需要传入请求方式、目标url和请求失败的监听。而在内部还定义了默认的请求重试策略new DefaultRetryPolicy()
public Request(int method, String url, Response.ErrorListener listener) { mMethod = method; mUrl = url; mErrorListener = listener; setRetryPolicy(new DefaultRetryPolicy()); mDefaultTrafficStatsTag = TextUtils.isEmpty(url) ? 0: Uri.parse(url).getHost().hashCode(); }
另外还对外提供获取请求方式的方法getMethod() 、获取tag的方法getTag() 设置重试策略的方法public void setRetryPolicy(RetryPolicy retryPolicy)等。
当一个request完成请求或是失败时,有一个finish方法,作用就是在请求队列中移除request。
/** * Notifies the request queue that this request has finished (successfully or with error). * 当请求成功或失败后,根据tag结束该请求 * <p>Also dumps all events from this request's event log; for debugging.</p> */ void finish(final String tag) { if (mRequestQueue != null) { mRequestQueue.finish(this); } }该方法其实主要是在RequestQueue内实现的,如下: /** * Called from {@link Request#finish(String)}, indicating that processing of * the given request has finished. * * 告诉请求队列,这个请求已经完成了。这个方法是在request内的finish方法调用的(注意请求完成(finish)和请求取消(cancel) * 是不同的概念,完成表示已经发送完网络请求并且拿回了数据,取消表示正在发送网络请求或拿数据但是还没完成) * * (1). 首先从正在进行中请求集合mCurrentRequests中移除该请求。 (2). * 然后查找请求等待集合mWaitingRequests中是否存在等待的请求 * ,如果存在,则将等待队列移除,并将等待队列所有的请求添加到缓存请求队列中,让缓存请求处理线程CacheDispatcher自动处理。 * <p> * Releases waiting requests for <code>request.getCacheKey()</code> if * <code>request.shouldCache()</code>. * </p> */ void finish(Request request) { // Remove from the set of requests currently being processed. //加锁,是因为多线程都有可能操作这个集合 synchronized (mCurrentRequests) { // 在当前对队列中将该请求给移除 mCurrentRequests.remove(request); } if (request.shouldCache()) { // 如果该请求是可以被缓存的 synchronized (mWaitingRequests) { String cacheKey = request.getCacheKey(); // 从等待队列中获取该key对应的所有的请求 Queue<Request> waitingRequests = mWaitingRequests .remove(cacheKey); if (waitingRequests != null) { if (VolleyLog.DEBUG) { VolleyLog .v("Releasing %d waiting requests for cacheKey=%s.", waitingRequests.size(), cacheKey); } // Process all queued up requests. They won't be considered // as in flight, but // that's not a problem as the cache has been primed by // 'request'.为什么要添加到缓存队列中,这是因为当一个请求已经完成,并且获取到了响应,就会将该请求标记为已完成也就是说需要再当前的请求队列中finish掉该请求,而在等待队列中存在的那些相同url的请求,就不需要再次发送网络请求了 // ,而认为是可以获取之前的请求的数据,因此需要将这些相同的请求从等待队列中移除,添加到缓存队列中,这样这些请求就会直接从缓存队列中获取数据,而不用再去发送网络请求了 mCacheQueue.addAll(waitingRequests); } } } }
需要注意的是,在Request中还定一了一个用于缓存的字段cacheEntry ,以及对应的cacheKey.。 在volley中默认的cacheKey是该request的url,这样能保证唯一性和重复请求的确定性,就是说当有多个请求是同一个url的时候,我们可以把除了第一个request外的其他request都放到等待队列中,这样就不用重复请求相同的url了,只需要请求一次,其他使用缓存就行了。而cachekey是判断是否同一request的标志。
/** * Returns the cache key for this request. By default, this is the URL. * 获得该Request的cachekey 该key用于在缓存时当做键来使用 */ public String getCacheKey() { //把请求的url当做key return getUrl(); }
大家都知道,当请求方式是post的时候,请求的参数是需要放在请求体中的,在Request中也提供了供开发者传入参数的方法getParams(),如果需要传入参数开发者需要重写该方法。
/** * 当是POST PUT请求的是时候,在请求时添加的参数需要在这里进行传递,也就是说当是POST的时候,想要传递参数就要重写getParams()方法 * Returns a Map of parameters to be used for a POST or PUT request. Can throw * {@link AuthFailureError} as authentication may be required to provide these values. * * <p>Note that you can directly override {@link #getBody()} for custom data.</p> * * @throws AuthFailureError in the event of auth failure */ protected Map<String, String> getParams() throws AuthFailureError { return null; }
在Request中定义了两个抽象方法,需要子类来实现:
/** * 子类重写此方法,将网络返回的原生字节内容,转换成合适的类型。此方法会在工作线程中被调用。 * * Subclasses must implement this to parse the raw network response * and return an appropriate response type. This method will be * called from a worker thread. The response will not be delivered * if you return null. * @param response Response from the network * @return The parsed response, or null in the case of an error */ abstract protected Response<T> parseNetworkResponse(NetworkResponse response); /** * 子类重写此方法,将解析成合适类型的内容传递给它们的监听回调。 * * Subclasses must implement this to perform delivery of the parsed * response to their listeners. The given response is guaranteed to * be non-null; responses that fail to parse are not delivered. * @param response The parsed response returned by * {@link #parseNetworkResponse(NetworkResponse)} */ abstract protected void deliverResponse(T response);
通过上边两个抽象方法,开发者可以定制自己的request。比如简单的StringRequest
StringRequest
public class StringRequest extends Request<String> { private final Listener<String> mListener; public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; } public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) { this(Method.GET, url, listener, errorListener); } @Override protected void deliverResponse(String response) { mListener.onResponse(response); } /* 完成将byte[]到String的转化, * 可能会出现字符乱码, * HttpHeaderParser.parseCharset(response.headers)方法在尚未指定是返回为ISO-8859-1, * 可以修改为utf-8*/ @Override protected Response<String> parseNetworkResponse(NetworkResponse response) { String parsed; try { //将data字节数据转化为String对象 parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } //返回Response对象,其中该对象包含访问相关数据 return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); }
- Volley的框架解读七(Request)
- Volley框架的基本解读(七)
- volley框架的解读
- Volley框架解析(七)-----Request解析
- Volley框架解读(二)
- Volley框架解读(三)
- Volley的框架解读一(Http的封装)
- Volley的框架解读三(字节流的优化)
- Volley的框架解读二(Http访问及处理)
- Volley的框架解读四(请求队列RequestQueue)
- Volley的框架解读五(网络调度NetworkDispatcher)
- Volley框架的基本解读(一)
- Volley框架的基本解读(二)
- Volley框架的基本解读(三)
- Volley框架的基本解读(四)
- Volley框架的基本解读(五)
- Volley框架的基本解读(六)
- Volley框架的基本解读(八)
- 互联网商业变现与计算广告(干货+5000字精彩问答)
- Hello Struts2
- 667. Beautiful Arrangement II
- 分页插件PageHelper
- listView加载
- Volley的框架解读七(Request)
- 深入浅出WPF之我见7
- UTC时间字符串转换为本地时间(北京)
- Tablayout+fragment
- EasyJoyStick使用以及两种操作杆 EasyJoyStick的使用方法,简单的不能再简单 Hedgehog Team-》Easy Touch -》Add Easy Touch For C#
- Linux驱动开发调试 -- 打开dev_dbg()
- Servlet下载文件代码
- string类的常用属性和方法
- springmvc的执行流程详解