@yudesong
2018-02-12T03:09:19.000000Z
字数 6403
阅读 618
volley

RequestQueue requestQueue = Volley.newRequestQueue(this);String url = "http://www.google.com";StringRequest stringquest = new StringRequest(Request.Method.GET,url, new Response.Listener<String>(){@Overridepublic void onResponse(String s) {re = s;callback.onSuccess(re);}}, new Response.ErrorListener(){@Overridepublic void onErrorResponse(VolleyError volleyError) {mNotices.setText(volleyError.getMessage());}});requestQueue.add(stringquest);
下面,通过Volley源码来简单了解一下其内部结构吧。

【1】首先来看看Volley这类。
public class Volley {private static final String DEFAULT_CACHE_DIR = "volley";public static RequestQueue newRequestQueue(Context context) {return newRequestQueue(context, null);}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 {stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));}}Network network = new BasicNetwork(stack);RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);queue.start();return queue;}}
【2】RequestQueue

public class RequestQueue {public void start() {stop(); // Make sure any currently running dispatchers are stopped.// 创建一个缓存调度线程并使之运行mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);mCacheDispatcher.start();// 默认创建4个网络调度线程并运行for (int i = 0; i < mDispatchers.length; i++) {NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,mCache, mDelivery);mDispatchers[i] = networkDispatcher;networkDispatcher.start();}}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;}//之前是否有执行相同的请求且还没有返回结果的,如果有的话将此请求加入mWaitingRequests队列,不再重复请求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 {//没有的话就将请求加入缓存队列mCacheQueue,同时加入mWaitingRequests中用来做下次同样请求来时的重复判断依据mWaitingRequests.put(cacheKey, null);mCacheQueue.add(request);}return request;}}}
【3】CacheDispatcher 缓存调度线程
public class CacheDispatcher extends Thread {@Overridepublic void run() {if (DEBUG) VolleyLog.v("start new dispatcher");Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);// Make a blocking call to initialize the cache.mCache.initialize();while (true) {try {// Get a request from the cache triage queue, blocking until// at least one is available.final Request<?> request = mCacheQueue.take();request.addMarker("cache-queue-take");// If the request has been canceled, don't bother dispatching it.if (request.isCanceled()) {request.finish("cache-discard-canceled");continue;}// Attempt to retrieve this item from cache.Cache.Entry entry = mCache.get(request.getCacheKey());if (entry == null) {request.addMarker("cache-miss");// Cache miss; send off to the network dispatcher.mNetworkQueue.put(request);continue;}// If it is completely expired, just send it to the network.if (entry.isExpired()) {request.addMarker("cache-hit-expired");request.setCacheEntry(entry);mNetworkQueue.put(request);continue;}// We have a cache hit; parse its data for delivery back to the request.request.addMarker("cache-hit");Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));request.addMarker("cache-hit-parsed");if (!entry.refreshNeeded()) {// Completely unexpired cache hit. Just deliver the response.mDelivery.postResponse(request, response);} else {// Soft-expired cache hit. We can deliver the cached response,// but we need to also send the request to the network for// refreshing.request.addMarker("cache-hit-refresh-needed");request.setCacheEntry(entry);// Mark the response as intermediate.response.intermediate = true;// Post the intermediate response back to the user and have// the delivery then forward the request along to the network.mDelivery.postResponse(request, response, new Runnable() {@Overridepublic void run() {try {mNetworkQueue.put(request);} catch (InterruptedException e) {// Not much we can do about this.}}});}} catch (InterruptedException e) {// We may have been interrupted because it was time to quit.if (mQuit) {return;}continue;}}}}
【4】NetworkDispatcher网络调度线程
public class NetworkDispatcher extends Thread {@Overridepublic void run() {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);Request<?> request;while (true) {try {// Take a request from the queue.request = mQueue.take();} catch (InterruptedException e) {// We may have been interrupted because it was time to quit.if (mQuit) {return;}continue;}try {request.addMarker("network-queue-take");// If the request was cancelled already, do not perform the// network request.if (request.isCanceled()) {request.finish("network-discard-cancelled");continue;}addTrafficStatsTag(request);// Perform the network request.NetworkResponse networkResponse = mNetwork.performRequest(request);request.addMarker("network-http-complete");// If the server returned 304 AND we delivered a response// already,// we're done -- don't deliver a second identical response.if (networkResponse.notModified&& request.hasHadResponseDelivered()) {request.finish("not-modified");continue;}// Parse the response here on the worker thread.Response<?> response = request.parseNetworkResponse(networkResponse);request.addMarker("network-parse-complete");// Write to cache if applicable.// TODO: Only update cache metadata instead of entire record for// 304s.if (request.shouldCache() && response.cacheEntry != null) {mCache.put(request.getCacheKey(), response.cacheEntry);request.addMarker("network-cache-written");}// Post the response back.request.markDelivered();mDelivery.postResponse(request, response);} catch (VolleyError volleyError) {parseAndDeliverNetworkError(request, volleyError);} catch (Exception e) {VolleyLog.e(e, "Unhandled exception %s", e.toString());mDelivery.postError(request, new VolleyError(e));}}}}