Volley框架的基本解读(二)
来源:互联网 发布:软件项目工作总结报告 编辑:程序博客网 时间:2024/05/21 21:38
在Volley框架的基本解读(一)中我们说了Volley与RequestQueue两个重要的类,说到了CacheDispatcher与NetworkDispatcher这两个调度类,比起缓存调度,我想大家可能会对网络调度更感兴趣,我们来看看:
public class NetworkDispatcher extends Thread
这个网络调度类本质是一个线程
public NetworkDispatcher(BlockingQueue<Request> queue, Network network, Cache cache, ResponseDelivery delivery) { mQueue = queue; mNetwork = network; mCache = cache; mDelivery = delivery;}
里面只有一个构造方法,从RequestQueue中传入的四个参数,分别是优先级队列,网络处理类,缓存处理类,结果分发类,回想一下,在RequestQueue的start方法中,NetworkDispatcher被创建后,便调用了NetworkDispatcher的start方法,因为它是一个线程,我们来看看run方法:
@Override public 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. // interrupt方法会尝试中断本线程,我们可能会被打断,因为这是该放弃的时候了 if (mQuit) { return; } continue; } try { // 调试标记:以成功取出队列中的request 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; } // Tag the request (if API >= 14) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { // 流量统计标记,配合DDMS工具统计流量使用情况 TrafficStats.setThreadStatsTag(request.getTrafficStatsTag()); } // 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. // 如果服务器返回无修改,并requset以完成分发,说明进行了重复的请求,移除该request if (networkResponse.notModified && request.hasHadResponseDelivered()) { request.finish("not-modified"); continue; } // Parse the response here on the worker thread. // 交由Request进行解析Response 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)); } } }
看重点,mQueue是一个用于保存requset的网络优先级队列,我们在使用volley框架时,通过mQueue.add(stringRequest)该方法将request加入到RequestQueue中,而在RequestQueue中又将该request加入了PriorityBlockingQueue<Request>这样一个以优先级排序的队列中,也就是这里的mQueue。
上面源码我们可以看到,run方法中是一个while死循环,不断的试图从mQueue队列中取出request,try.....catch中的意义等会再说,然后就是各种判断,如果request标记取消,就结束这次网络请求,如果api大于14,进行流量统计,后面这句代码是重点:
// 前戏结束,这里就是真正的网络请求NetworkResponse networkResponse = mNetwork.performRequest(request);
现在我们知道,NetworkDispatcher为什么是网络调度线程?因为它只负责将request传给mNetwork网络处理类,本身并不执行网络请求。
接着看,如果请求结果无修改并requset以完成分发,说明进行了重复的请求,结果无需返回。NetworkResponse是一个对返回结果封装的实体类,request对其进行解析,parseNetworkResponse该方法是一个抽象方法,request可以有很多具体实现子类,因此解析的方式只能由子类具体实现,如果需要缓存,将返回的数据加入缓存处理类中,最后由结果分发类调用postResponse(request, response)发起回调。
这里的内容有点多,可能有点乱,但多数是简单的判断,大家明白意义即可,具体的下面分析,在此之前我们再看两个方法:
/** * 通知错误 */private void parseAndDeliverNetworkError(Request<?> request, VolleyError error) { error = request.parseNetworkError(error); mDelivery.postError(request, error);}
在上面的run方法中当catch捕捉到VolleyError异常,便会交给该方法处理,大概意思就是让request.parseNetworkError(error)解析这个错误,然后发起错误回调,值得一提的是parseNetworkError在request中是一个没有意义的方法,传进去的VolleyError会被原封不动的返回,但子类可以复写该方法,完成自己的错误解析。
/** * Forces this dispatcher to quit immediately. If any requests are still in * the queue, they are not guaranteed to be processed. * * 标记取消网络请求,并中断该线程 */ public void quit() { mQuit = true; interrupt(); }
这个方法大家看的是不是有点眼熟,它正是RequestQueue的stop方法中出现的,用于中断线程,代码很简单,改变了标记并调用了interrupt这个Thread中定义的尝试中断线程的方法,如果这个方法被调起,线程被中断会出现什么情况?大家想起了上面run方法中的try......catch了没,在catch中有这么一段代码:
// interrupt方法会尝试中断本线程,我们可能会被打断,因为这是该放弃的时候了if (mQuit) { return;}continue;
interrupt方法会尝试中断本线程,while死循环即会抛出异常,mQuit为true,while循环被跳出,逻辑相当的精巧,有木有!
- Volley框架的基本解读(二)
- Volley框架的基本解读(一)
- Volley框架的基本解读(三)
- Volley框架的基本解读(四)
- Volley框架的基本解读(五)
- Volley框架的基本解读(六)
- Volley框架的基本解读(七)
- Volley框架的基本解读(八)
- volley框架的解读
- Volley框架解读(二)
- Volley的框架解读二(Http访问及处理)
- Volley的框架解读准备一HttpURLConnection
- Volley的框架解读七(Request)
- Volley框架的基本使用方法
- Volley框架的基本使用方法
- Volley框架之二 基本流程
- Volley框架之二 基本流程
- Volley===Volley框架的基本使用方法
- 多媒体页面
- DLLImport:无法加载 DLL
- Javascript中的Callback方法浅析
- Ubuntu下安装arm-linux-gnueabi-xxx编译器
- Python的一点人生经验
- Volley框架的基本解读(二)
- iOS开发--内存管理--学习手动内存管理暂时抛弃ARC以及retain/assign知识
- easyui入门一
- makefile与gdb调试
- Android AlarmManager实现不间断轮询服务
- RxJava分析之订阅过程
- java synchronized详解
- Apache配置中ProxyPass与ProxyPassReverse及ProxyPassMatch的概述
- Java - 蓝桥杯 - 历届试题 翻硬币