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循环被跳出,逻辑相当的精巧,有木有!



0 0
原创粉丝点击