Volley框架的基本解读

Posted zero-27

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Volley框架的基本解读相关的知识,希望对你有一定的参考价值。

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源码解读(上)