您的位置:首页 > 产品设计 > UI/UE

Android中的volley_11_Request

2015-06-05 20:07 435 查看
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。

demo下载地址:http://download.csdn.net/detail/vvzhouruifeng/8747599
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: