Volley源码学习(三):线程处理request,类CacheDispatcher,NetworkDispatcher,ExecutorDelivery
2016-03-16 20:42
316 查看
一.源码解析
volley处理request的流程:当调用RequestQueue的add(request)方法时,会进行一系列逻辑判断:如先从cache获取,没有或者过期,再从网络获取。这是通过将request添加到CacheQueue和NetworkQueue里,最终是由线程类CacheDispatcher,NetworkDispatcher进行相应处理的。
1.类CacheDispather,缓存请求处理线程类,在RequestQueue的start方法里启动线程类,一直循环读取request,如果cache里没有或过期,然后添加request到networkQueue里从网络获取→有,将cacheentry变成networkresponse,并用request解析成response→不需更新就直接用mDelivery.postResponse(request, response);,需更新就之后再从网络获取
public CacheDispatcher( BlockingQueue<Request> cacheQueue, BlockingQueue<Request> networkQueue, Cache cache, ResponseDelivery delivery) { mCacheQueue = cacheQueue; //读取request,进行cache的操作 mNetworkQueue = networkQueue; //将request add到networkqueue里进行网络请求 mCache = cache; //cache缓存,这里使用DiskBasedCache(cacheDir),将文件缓存到本地 mDelivery = delivery; //用于将respone发送给request里的listener的方法 }
@Override public 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(); //从CacheQueue里获得request,没有就阻塞 request.addMarker("cache-queue-take"); // If the request has been canceled, don't bother dispatching it. if (request.isCanceled()) { //如果request被取消,就finish 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()) { //cache过期,去网络请求 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( //调用request方法解析networkResponse为response new NetworkResponse(entry.data, entry.responseHeaders)); <span style="font-family: Arial, Helvetica, sans-serif;">//将cacheentry变成networkResponse</span> request.addMarker("cache-hit-parsed"); if (!entry.refreshNeeded()) { //不需要更新就自己delivery response到对应request的listener // 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() { //postResponse后再从网络更新Cache @Override public 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; } } }
2.类NetworkDispatcher,线程处理网络请求
从queue里获取request→先判定是否取消,然后finish(request)→网络请求response = request.parseNetworkResponse(networkResponse);→
response = request.parseNetworkResponse(networkResponse);解析成response→需要缓存就调用mCache的put方法→mDelivery.postResponse(request, response);发送结果→异常时发送错误
public NetworkDispatcher(BlockingQueue<Request> queue, Network network, Cache cache, ResponseDelivery delivery) { mQueue = queue; mNetwork = network; mCache = cache; mDelivery = delivery; }<pre name="code" class="html"> @Override public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Request request; while (true) { try { // Take a request from the queue. request = mQueue.take(); //获取request,没有就阻塞 } 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 request.finish("network-discard-cancelled"); continue; } // Tag the request (if API >= 14) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { TrafficStats.setThreadStatsTag(request.getTrafficStatsTag()); } // Perform the network request. NetworkResponse networkResponse = mNetwork.performRequest(request); //获得networkResponse 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()) { //如果没修改且已经发送repsonse,结束request request.finish("not-modified"); continue; } // Parse the response here on the worker thread. Response<?> response = request.parseNetworkResponse(networkResponse); //解析成response 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); //将response结果post到requst的listener里,实际转接 } catch (VolleyError volleyError) { parseAndDeliverNetworkError(request, volleyError); //异常时发送错误 } catch (Exception e) { VolleyLog.e(e, "Unhandled exception %s", e.toString()); mDelivery.postError(request, new VolleyError(e)); } } }
3.类ExecutorDelivery,用于发送response或error到request的listener
使用主线程的looper来处理线程。调用postResponse方法时处理一次线程,将response和error传给requset
public ExecutorDelivery(final Handler handler) { //handler使用主线程Looper.getMainLooper() // Make an Executor that just wraps the handler. mResponsePoster = new Executor() { @Override public void execute(Runnable command) { handler.post(command); } }; } @Override public void postResponse(Request<?> request, Response<?> response, Runnable runnable) { request.markDelivered(); request.addMarker("post-response"); mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable)); }<pre name="code" class="html"> @Override public void postError(Request<?> request, VolleyError error) { request.addMarker("post-error"); Response<?> response = Response.error(error); mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null)); }
@SuppressWarnings("rawtypes") private class ResponseDeliveryRunnable implements Runnable { private final Request mRequest; private final Response mResponse; private final Runnable mRunnable; public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) { mRequest = request; mResponse = response; mRunnable = runnable; } @SuppressWarnings("unchecked") @Override public void run() { // If this request has canceled, finish it and don't deliver. if (mRequest.isCanceled()) { //取消就结束 mRequest.finish("canceled-at-delivery"); return; } // Deliver a normal response or error, depending. if (mResponse.isSuccess()) { //成功就调用request的方法,获得reponse.data mRequest.deliverResponse(mResponse.result); } else { mRequest.deliverError(mResponse.error); //失败,就调用request的方法获得response.error } // If this is an intermediate response, add a marker, otherwise we're done // and the request can be finished. if (mResponse.intermediate) { mRequest.addMarker("intermediate-response"); } else { mRequest.finish("done"); } // If we have been provided a post-delivery runnable, run it. if (mRunnable != null) { mRunnable.run(); } } }
相关文章推荐
- iOS UIView animation动画效果 (1)
- easyui 列表里下拉框联动
- UI进阶——SQL数据库
- android:finishOnTaskLaunch="true" //虽然这样设置了,但是Back键与Home键还是不同
- torque
- 给UIButton设置BackgroundColor:forState
- guice框架的入门使用
- (4.5.3.4)finished with non-zero exit value 2
- UI组件:PopupWindows的详细使用(一)
- U3D打包DLL插件 DLL Builder
- UITableView传值(自己使用)(属性,代理传值)
- iOS UITextField设置金额(钱数)输入框
- iOS--页面跳转(UITableView)
- NGUI中打字效果TypewriterEffect的一个BUG
- POJ 2229 Ultra-QuickSort 归并排序求逆序数
- Number Sequence (HDU_1711) KMP
- build模式小例子
- [ShareSDK] QuickIntegrater.jar文件各种打不开
- UITextField - 解决键盘遮住View & 密文设定 & 实例
- 今天遇到 Request failed: method not allowed (405)。 错误,特此在网上翻了翻