volley源码解析

}//(2.1)


public RequestQueue(Cache cache, Network network, int threadPoolSize) {

this(cache, network, threadPoolSize,//ExecutorDelivery类是Volley框架中的结果分发类

        new ExecutorDelivery(new Handler(Looper.getMainLooper())));//传入Handler是为了能够让需要的方法跑在主线程

}//(2.2)


public RequestQueue(Cache cache, Network network, int threadPoolSize,

    ResponseDelivery delivery) {

mCache = cache;//缓存处理类的实例

mNetwork = network;//网络处理类的实例

mDispatchers = new NetworkDispatcher[threadPoolSize];//网络调度器的实例

mDelivery = delivery;//结果分发类的实例

}//(2.3)


到这儿终于创建好RequestQueue了,紧接着是start,开启1条缓存调度和4条网络调度。


public void start() {

stop();  // 终止正在运行的线程,缓存调度mCacheDispatcher.quit(),网络调度mDispatchers循环quit(),暂停线程

mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);

mCacheDispatcher.start();//开启缓存调度

for (int i = 0; i < mDispatchers.length; i++) {//开启网络调度,一般4条

    NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,

            mCache, mDelivery);

    mDispatchers[i] = networkDispatcher;

    networkDispatcher.start();

}

}(2.4)




(3)网络调度类NetworkDispatcher,这个类继承Thread类,本身是一个线程,只有一个构造方法,重写了run方法。



NetworkDispatcher只负责调度并不负责具体的网络请求,它相当于一个中转站,只是将request从RequestQueue手中取来,然后原封不动的交给mNetwork



public NetworkDispatcher(BlockingQueue<Request<?>> queue,Network network, Cache cache, ResponseDelivery delivery) {

mQueue = queue;//优先级队列

mNetwork = network;//网络处理器

mCache = cache;//缓存处理器

mDelivery = delivery;//结果分发类

}(3.1)




在请求队列start()的时候,就创建并开启了4条网络线程调度,所以看下NetworkDispatcher的run方法:



@Override

public void run() {

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//设置最高线程优先级

while (true) {//while死循环,不断的试图从mQueue队列中取出request

    long startTimeMs = SystemClock.elapsedRealtime();

    Request<?> request;

    try {

        request = mQueue.take();

    } catch (InterruptedException e) {

        if (mQuit) {//interrupt()会尝试中断本线程,我们可能会被打断,因为这是该放弃的时候了

            return;

        }

        continue;

    }



    try {

        request.addMarker("network-queue-take");// 调试标记:以成功取出队列中的request

        if (request.isCanceled()) {//如果请求被取消,则不再继续请求

            request.finish("network-discard-cancelled");

            continue;

        }

        addTrafficStatsTag(request);// 流量统计标记,如果api大于14,配合DDMS工具统计流量使用情况

        // 开始真正的网络请求,从这儿看出NetworkDispatcher为什么是网络调度线程,因为它只负责将request传给mNetwork网络                                               

处理类,本身并不执行网络请求,这个方法返回的是NetworkResponse(一个实体类,封装返回数据,封装的参数分别是int状态码,byta[]返回数据,Map<String,String>响应头,boolean无修改标记)

        NetworkResponse networkResponse = mNetwork.performRequest(request);

        request.addMarker("network-http-complete");//调试标记:网络请求完成(因线程异步,该标记只做调试之用)

        // 如果服务器返回无修改,并requset以完成分发,说明进行了重复的请求,移除该request

        if (networkResponse.notModified && request.hasHadResponseDelivered()) {

            request.finish("not-modified");

            continue;

        }

        // 交由Request进行解析Response

//parseNetworkResponse是Request抽象类的一个抽象方法,实现方法由Request的子类去实现

        Response<?> response = request.parseNetworkResponse(networkResponse);

        request.addMarker("network-parse-complete");// 调试标记:网络请求解析完成

        // 如果需要缓存,将返回的数据加入到缓存处理类中

        if (request.shouldCache() && response.cacheEntry != null) {

            mCache.put(request.getCacheKey(), response.cacheEntry);

            request.addMarker("network-cache-written");

        }

        // 最后由结果分发类调用postResponse发起回调

        request.markDelivered();

        mDelivery.postResponse(request, response);

    } catch (VolleyError volleyError) {

        volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);

parseAndDeliverNetworkError(request, volleyError); //此方法通过request.parseNetworkError(volleyError)解析这个错误,然后发起错误回调,值得一提的是parseNetworkError在request中是一个没有意义的方法,传进去的VolleyError会被原封不动的返回,但子类可以复写该方法,完成自己的错误解析。

    } catch (Exception e) {

        VolleyLog.e(e, "Unhandled exception %s", e.toString());

        VolleyError volleyError = new VolleyError(e);

        volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);

        mDelivery.postError(request, volleyError);

    }

}

}(3.2)


public void quit() {//在RequestQueue调用stop时被调用了

mQuit = true;//标记取消网络请求,并中断该线程,mQuit 为true,则该线程跳出while循环

interrupt();

}(3.3)




`(4)NetworkDispatcher只负责中转,从RequestQueue取出request交给接口NetWork,BasicNetwork是接口的实现类:`



public interface Network {//里面只有一个方法,用于执行请求

public NetworkResponse performRequest(Request<?> request) throws VolleyError;

}(4.1)

在newRequestQueue时,实现了网络接口,Network network = new BasicNetwork(stack);,随后这个network便传给了请求队列,然后又传给网络调度器,最后调用mNetwork.performRequest(request)执行网络请求。


public BasicNetwork(HttpStack httpStack) {//在newRequestQueue时新建的构造方法

this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE));//创建了缓存池,大小4096,即4KB

}(4.2)


public BasicNetwork(HttpStack httpStack, ByteArrayPool pool) {

mHttpStack = httpStack;

mPool = pool;

}(4.3)


(4.4)performRequest返回的是一个封装返回数据的实体类对象。这个方法只是对网络请求返回数据的封装处理

@Override

public NetworkResponse performRequest(Request<?> request) throws VolleyError {

long requestStart = SystemClock.elapsedRealtime();//得到开机时间的毫秒值

while (true) {//while死循环

    HttpResponse httpResponse = null;

    byte[] responseContents = null;

    Map<String, String> responseHeaders = Collections.emptyMap();

    try {

        Map<String, String> headers = new HashMap<String, String>();

        addCacheHeaders(headers, request.getCacheEntry());//添加缓存请求头

        httpResponse = mHttpStack.performRequest(request, headers);//看出真正执行网络请求的是mHttpStack

        StatusLine statusLine = httpResponse.getStatusLine();//得到状态行

        int statusCode = statusLine.getStatusCode();//得到状态码

        responseHeaders = convertHeaders(httpResponse.getAllHeaders());//得到响应头

        if (statusCode == HttpStatus.SC_NOT_MODIFIED) {//返回304无修改,则返回

            return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, statusLine.getReasonPhrase(), entry.data,

                    entry.responseHeaders, true,

                    SystemClock.elapsedRealtime() - requestStart);               

        }        

        if (httpResponse.getEntity() != null) {//返回204无修改,没有读出内容就给一个0长度字节的数组

          responseContents = entityToBytes(httpResponse.getEntity());

        } else {

          responseContents = new byte[0];

        }

        // if the request is slow, log it.

        long requestLifetime = SystemClock.elapsedRealtime() - requestStart;

        logSlowRequests(requestLifetime, request, responseContents, statusLine);//调试信息



        if (statusCode < 200 || statusCode > 299) {

            throw new IOException();//状态码不正确抛出异常

        }//经过以上种种判断,封装成NetWorkResponse给予返回

        return new NetworkResponse(statusCode, statusLine.getReasonPhrase(), responseContents, responseHeaders, false,SystemClock.elapsedRealtime() - requestStart);//返回封装的数据,状态码,返回数据,响应头,无修改标记

    } catch (SocketTimeoutException e) {//尝试重新请求,重试策略类RetryPolicy,在Request的构造方法中创建,先获取对象

        attemptRetryOnException("socket", request, new TimeoutError());//retryPolicy= request.getRetryPolicy();

    } catch (ConnectTimeoutException e) {//然后调用retryPolicy.retry(exception);

        attemptRetryOnException("connection", request, new TimeoutError());

    } catch (MalformedURLException e) {

        throw new RuntimeException("Bad URL " + request.getUrl(), e);

    } catch (IOException e) {

        int statusCode = 0;

        NetworkResponse networkResponse = null;

        if (httpResponse != null) {

            statusCode = httpResponse.getStatusLine().getStatusCode();

        } else {

            throw new NoConnectionError(e);

        }

        VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());

        if (responseContents != null) {

            networkResponse = new NetworkResponse(statusCode, httpResponse.getStatusLine().getReasonPhrase(), responseContents,

                    responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);

            if (statusCode == HttpStatus.SC_UNAUTHORIZED ||

                    statusCode == HttpStatus.SC_FORBIDDEN) {

                attemptRetryOnException("auth",

                        request, new AuthFailureError(networkResponse));

            } else {

                // TODO: Only throw ServerError for 5xx status codes.

                throw new ServerError(networkResponse);

            }

        } else {

            throw new NetworkError(networkResponse);

        }

    }

}

}




(5)HttpStack的源码



//Request封装了超时时间,请求方式、参数、url等网络请求所必须的参数,通过变换不同的属性参数(最基本的如请求方式GET和Post),可以获取不同的网络请求。而真正的网络请求是HttpStack



public interface HttpStack {Volley中真正去执行联网的类,返回的信息封装成HttpResponse  

  public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)throws IOException, AuthFailureError;//真正去执行联网的方法,与NetWork接口的一个方法同名  

}



对于HttpClientStack和HurlStack,二者的工作思路是:



首先从volley的request内获取各个属性,如超时间、请求方式、url、参数;



然后创建网络请求,HttpClientStack创建HttpClient,HurlStack创建HttpURLConnection;



对网络请求设置各个属性参数。



最后定义执行网络请求的方法,并获取响应,将响应返回去。



以上思路在源码细节中是从HurlStack的performRequest开始



public HurlStack() {this(null);}


public HurlStack(UrlRewriter urlRewriter) {this(urlRewriter, null);}


public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {

mUrlRewriter = urlRewriter;//是HurlStack的一个内部接口,用于URL的重置,一般给null

mSslSocketFactory = sslSocketFactory;//https协议用到的类,一般也是null

}




![](https://img-blog.csdnimg.cn/20190827220442739.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppdWppYW9wYW5kdW9sYQ==,size_16,color_FFFFFF,t_70)



![](https://img-blog.csdnimg.cn/20190827220735869.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppdWppYW9wYW5kdW9sYQ==,size_16,color_FFFFFF,t_70)



其中传入的参数request,里面设置了很多http的属性,如超时,是否缓存,还有一个参数设置头信息



再看看其中几个重要方法:openConnection,setConnectionParametersForRequest ,entityFromConnection



private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {

HttpURLConnection connection = createConnection(url);//很简单,只是创建了HttpURLConnection,

通过 url.openConnection()

int timeoutMs = request.getTimeoutMs();

connection.setConnectTimeout(timeoutMs);//设置HttpURLConnection的一些参数,连接超时

connection.setReadTimeout(timeoutMs);//读超时

connection.setUseCaches(false);//关闭缓存

connection.setDoInput(true);//开启输入

if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {//支持https

    ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);

}

return connection;//返回HttpURLConnection对象

}




setConnectionParametersForRequest :设置请求方式,包含get,delete,post,put等



private static HttpEntity entityFromConnection(HttpURLConnection connection) {

BasicHttpEntity entity = new BasicHttpEntity();//设置实体

InputStream inputStream;

try {

    inputStream = connection.getInputStream();

} catch (IOException ioe) {

    inputStream = connection.getErrorStream();

}

entity.setContent(inputStream);

entity.setContentLength(connection.getContentLength());

entity.setContentEncoding(connection.getContentEncoding());

entity.setContentType(connection.getContentType());

return entity;//将connection得到的信息封装成实体(BasicHttpEntity)返回

}




到这儿volley网络请求这一条线已经全部完成。



(6)接下来看缓存调度器CacheDispatcher,也是一个线程,继承Thread,也是在请求队列的start方法中调用的start方法



public CacheDispatcher(

    BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue,

    Cache cache, ResponseDelivery delivery) {

mCacheQueue = cacheQueue;//缓存队列

mNetworkQueue = networkQueue;//网络队列

mCache = cache;//缓存处理类

mDelivery = delivery;//结果分发类

}


@Override

public void run() {

if (DEBUG) VolleyLog.v("start new dispatcher");

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

mCache.initialize();//将缓存数据读入内存,初始化了缓存数据

while (true) {

    try {

        final Request<?> request = mCacheQueue.take();//从缓存队列中取出request

        request.addMarker("cache-queue-take");//调试信息

        if (request.isCanceled()) {//如果请求已取消,则中断任务

            request.finish("cache-discard-canceled");

            continue;

        }

        Cache.Entry entry = mCache.get(request.getCacheKey());//试图从缓存中取得该项目

        if (entry == null) {//是空的就加入网络队列

            request.addMarker("cache-miss");

            mNetworkQueue.put(request);

            continue;

        }

        if (entry.isExpired()) {//如果缓存过期,加入网络队列

            request.addMarker("cache-hit-expired");

            request.setCacheEntry(entry);

            mNetworkQueue.put(request);

            continue;

        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值