上节写到关于
Vollery
的前半部分,需要查看的点击 这里 , 这次主要查看当我们真正add request
的时候做进一步查看。
我们还是从使用的方法作为我们的切入点:
mQueue.add(postRequest);//当我们向队列中添加一个网络请求
跟进,查看 RequestQueue#add()
方法:
/** * Staging area for requests that already have a duplicate request in * flight. * 存储有重复请求的request暂存区,我个人认为就是如果 正在处理A发出的一个请求,此时又来一个A发出同样的一个请求,那么第二个请求就会暂时保存在这个集合中 */private final Map<String, Queue<Request<?>>> mWaitingRequests = new HashMap<String, Queue<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. //判断是否可以缓存了,不缓存就添加到网络请求队列中去return,前面已经说过这个 mNetworkQueue 存储管理网络请求队列的 //默认是可以缓存的,在Request的构造方法可以看到 //public Request(int method, String url, ErrorListener listener) { // this.mShouldCache = true; // } 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) { //首先查看是否缓存过,取key 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); } else { //第一次请求,应该是进入到这里的 // Insert 'null' queue for this cacheKey, indicating there is // now a request in // flight. //添加一个 null 队列,表示有一个请求正在进行 mWaitingRequests.put(cacheKey, null); //添加到缓存队列中,那么我们接下来重点查看CacheDispatcher#run方法 mCacheQueue.add(request); } return request; } }
接下来就到 CacheDispatcher#run()
方法了,因为里面有值了。
public void run() { Process.setThreadPriority(10); //初始化缓存类型有两种目前:NoCache() 和 DiskBaseCache() this.mCache.initialize(); //嵌套了好多 while 循环 while(true) { while(true) { while(true) { while(true) { try { //从缓存队列中取出,在之前第一篇文章时,没展示下半部分,这次有请求就可以看下里面的逻辑了。 final Request<?> request = (Request)this.mCacheQueue.take(); request.addMarker("cache-queue-take"); //请求未取消 if (request.isCanceled()) { request.finish("cache-discard-canceled"); } else { //拿到缓存结果,请求信息都保存一个叫Entry内部类中 Entry entry = this.mCache.get(request.getCacheKey()); //有可能取出的缓存为null if (entry == null) { request.addMarker("cache-miss"); //如果清空了缓存,那就重新添加到网络请求队列中去 this.mNetworkQueue.put(request); } else if (!entry.isExpired()) {//判断是否过期 request.addMarker("cache-hit"); //拿到请求结果response Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders)); request.addMarker("cache-hit-parsed"); //表示是否需要重新刷新 if (!entry.refreshNeeded()) { //不需要的话就直接分发给主线程了 this.mDelivery.postResponse(request, response); } else { //需要刷新,就重新进行网络请求 request.addMarker("cache-hit-refresh-needed"); request.setCacheEntry(entry); response.intermediate = true; this.mDelivery.postResponse(request, response, new Runnable() { public void run() { try { ////需要刷新,就重新进行网络请求 CacheDispatcher.this.mNetworkQueue.put(request); } catch (InterruptedException var2) { ; } } }); } } else { //表示过期了,也重新进行请求 request.addMarker("cache-hit-expired"); request.setCacheEntry(entry); this.mNetworkQueue.put(request); } } } catch (InterruptedException var4) { if (this.mQuit) { return; } }
关于 CacheDispatcher#run
类我画了一张图示:
CacheDispatcher.png
从这里我们知道,网络请求首先需要mCacheDispatcher
判断是否已缓存,若缓存了则直接 postResponse
如果没有,则重新进行网络请求,我们就直接添加到 mNetworkQueue
中,那第一次请求,肯定还未缓存, 那我们下面就又可以看这个 NetworkDispatcher#run
方法了,因为此时队列中有请求了,接下来我们再返回查看:
NetworkDispatcher#run()
方法:
public void run() { //设置线程优先级 Process.setThreadPriority(10); while(true) { Request request; while(true) { try { //从这个网络请求队列中中取出一条request //第二次这里有了,因为我们add 了 一个 request request = (Request)this.mQueue.take(); break; } catch (InterruptedException var4) { if (this.mQuit) { return; } } } //以下都是网络请求队列有网络请求任务时执行 request.addMarker("network-queue-take"); if (request.isCanceled()) {//判断是否取消 request.finish("network-discard-cancelled"); } else { //网络请求未取消 this.addTrafficStatsTag(request); //处理网络请求,得到NetworkResponse NetworkResponse networkResponse = this.mNetwork.performRequest(request); //标识请求完成 request.addMarker("network-http-complete"); if (networkResponse.notModified && request.hasHadResponseDelivered()) { request.finish("not-modified"); } else { //开始解析返回的结果,解析parseNetworkResponse可根据不同类型的方式进行解析,请看下图: Response<?> response = request.parseNetworkResponse(networkResponse); //标识解析完成 request.addMarker("network-parse-complete"); //开始缓存请求结果,判断是否可以缓存,默认可以 if (request.shouldCache() && response.cacheEntry != null) { this.mCache.put(request.getCacheKey(), response.cacheEntry); request.addMarker("network-cache-written"); } //分发请求结果通过 mDelivery 完成 request.markDelivered(); this.mDelivery.postResponse(request, response); } } }
解析 有Json
Image
String
等多种类型。
image.png
到此基本分析完毕。奉上一个整体流程图,我在网上找到的,感觉还不错:
作者:糖葫芦_倩倩
链接:https://www.jianshu.com/p/ef7add941804
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦