本文主要大概介绍Volley框架源码的骨干东西,内部队列调度,业务流程不详细说。
使用Volley的过程很简单
1、newRequestQueue获取请队列;
2、mQueue.add(stringRequest);将请求加入队列
RequestQueue mQueue = Volley.newRequestQueue(context);
StringRequest stringRequest = new StringRequest(StringRequest.Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.i(TAG, "response:" + response);
iRequest.onResult(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "error:" + error);
ExVolleyException exception = new ExVolleyException();
if(error.networkResponse != null){
iRequest.onError(exception.getStatusError(error.networkResponse.statusCode));
}else {
iRequest.onError(exception.getStatusError(500));
}
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return getRequestHeaders(TYPE_HEADER.TYPE_NORMAL);
}
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return super.getParams();
}
};
mQueue.add(stringRequest);
=======================================================
先从newRequestQueue进入源码分析
一、Volley.class—–>newRequestQueue(Context,HttpStack)
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
String userAgent = "volley/0";
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException e) {
}
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
(1) 主要是根据版本是否大于9(android2.3),初始化HttpStack,主要的区别是:用于网络请求的方式,根据不同的HttpStack初始化,后面用于请求网络的方式不一样,大于9的初始化的HttpStack后面的请求用的HttpUrlConnection而小于9的初始化,后面请求网络用的是httpClient。
(2)初始化BasicNetwork(实现了Network)实际的请求网络的类
(3)初始化一个队列,并将初始化好的缓存和网络请求实例入参
(4)queue.start();
/**
* Starts the dispatchers in this queue.
*/
public void start() {
stop(); // Make sure any currently running dispatchers are stopped.
/*
* @param cacheQueue Queue of incoming requests for triage
* @param networkQueue Queue to post requests that require network to
* @param cache Cache interface to use for resolution
* @param delivery Delivery interface to use for posting responses
*/
// Create the cache dispatcher and start it.
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();
// Create network dispatchers (and corresponding threads) up to the pool size.
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
主要是缓存调度器和网络请求调度器的初始化及start;
两个调度器均继承线程,在RequestQueue构造时,默认缓存调度器线程有4个;
二、mQueue.add(stringRequest); RequestQueue—->add(Request)方法分析
/**
* Adds a Request to the dispatch queue.
* @param request The request to service
* @return The passed-in request
*/
public <T> Request<T> add(Request<T> request) {
// Tag the request as belonging to this queue and add it to the set of current requests.
request.setRequestQueue(this);
synchronized (mCurrentRequests) {
mCurrentRequests.add(request);
}
// Process requests in the order they are added.
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
// If the request is uncacheable, skip the cache queue and go straight to the network.
if (!request.shouldCache()) {
mNetworkQueue.add(request);
return request;
}
// Insert request into stage if there's already a request with the same cache key in flight.
synchronized (mWaitingRequests) {
String cacheKey = request.getCacheKey();
if (mWaitingRequests.containsKey(cacheKey)) {
// There is already a request in flight. Queue up.
Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
if (stagedRequests == null) {
stagedRequests = new LinkedList<Request<?>>();
}
stagedRequests.add(request);
mWaitingRequests.put(cacheKey, stagedRequests);
if (VolleyLog.DEBUG) {
VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
}
} else {
// Insert 'null' queue for this cacheKey, indicating there is now a request in
// flight.
mWaitingRequests.put(cacheKey, null);
mCacheQueue.add(request);
}
return request;
}
}
流程大概就是:
1、 request.setRequestQueue(this);请求帮顶请求队列
2、 mCurrentRequests.add(request);同步加入当前请求队列
3、 request.setSequence(getSequenceNumber());
request.addMarker(“add-to-queue”);
请求加标记
4、判断是否缓存,不缓存就直接放到请求队列: mNetworkQueue.add(request);
5、 判断请求等待队列是否包含当前请求:if(mWaitingRequests.containsKey(cacheKey))及是否有相 同请求正在被处理
如果包含,加入到相同请求的等待队列中,
不包含则创建新的当前请求的空队列,添加当前请求到缓存请求队列中
三、最后
在初始化请求队列的时候重新开启了5个线程,4个缓存调度线程组成的缓存调度器,一个请求调度线程,然后具体的缓存、请求逻辑,请求的实现就交给了调度器,这也是volley框架的核心部分,是很细节的地方,主要关注两类调度器里面run方法。