前面的三篇Volley框架解析文章已经从Volley对外暴露的接口Volley.java开始,向下慢慢深入到了RequestQueue.java,这个Volley中比较核心的类,然后又分析了Volley中负责主要request调度工作的两类Dispatcher,NetworkDispatcher
以及CacheDispatcher
。应该是将一个request从新建,到加入队列中等待处理,如何被处理以及返回结果或者error这一系列的流程理顺了。
但是对于一些细节的问题还是不清楚,例如request究竟是如何发送出去,通过NetworkResponse networkResponse = mNetwork.performRequest(request);
这么一句话就返回了结果(response),这里面发生了些什么还不得而知,还有{#link Network#performRequest()}
和{#link HttpStack#performREquest()}
这两个函数之间有什么区别和联系等等。
最早接触到Network这个类是在Volley.java
中的newRequestQueue()
函数里面,Network network = new BasicNetwork(stack);
创建了一个Network接口引用,并指向了一个Volley中的默认实现类的实例BasicNetwork.java
,这个默认实现类也会在这篇博客的后面详细的解析。
经过前面几篇博客的分析,Volley.java
仅仅是持有而没有使用,仅将这个引用传递给了NetworkDispatcher.java
中,只有在NetworkDispatcher.java
类中用到了这个Network接口,在NetowkrDispatcher.java
中存在着这么一行代码,
NetworkResponse networkResponse = mNetwork.performRequest(request);
仅仅用了一句话就将request发送出去了,并且还拿回来了一个NetworkResponse.java
类对象。里面发生了什么= =,先进去Network.java里面看看:
package com.android.volley;
/**
* An interface for performing requests.
*/
public interface Network {
/**
* Performs the specified request.
* 用来发送特定的请求
*
* @param request Request to process
* 即将被发送的request
*
* @return A {@link NetworkResponse} with data and caching metadata; will never be null
* 请求之后返回的response, 是volley自己构造出来的一个response
* 里面包含了返回的请求码等等。
*
* @throws VolleyError on errors
*/
public NetworkResponse performRequest(Request> request) throws VolleyError;
}
对,没有看错= =,就这么点东西,仅仅一个抽象方法而已,Network.java就是一个等待被实现的接口,想看真东西,还需要进去Network network = new BasicNetwork(stack);
里面所提到的BasicNetwork.java
看看。
Network.java
接口的默认实现类,该类里面会处理一些request发送前后的处理工作,主要是对请求返回的httpResponse处理,以及对请求失败进行retry或者抛出异常的处理。
package com.android.volley.toolbox;
/**
* A network performing Volley requests over an {@link HttpStack}.
* 一个用来执行Volley中request的类
* 在HttpStack的基础之上
* 因为主要还是调用HttpStack接口的performRequest
* 在这个里面的performRequest主要还是做一些整理工作
* 比如将{@link HttpStack#performRequest()}方法返回的HttpResponse
* 解析成Volley自己实现的NetworkResponse.java
*/
public class BasicNetwork implements Network {
//是否允许打lo的boolean常变量
protected static final boolean DEBUG = VolleyLog.DEBUG;
/**
* 这是一个阀值,用来判断一个request是否请求响应过慢了= =
* 在后面的作用就是,如果响应时间超过了这个阀值
* 打出log说明这个request有些慢,为了更好的反应request当前状态
*/
private static int SLOW_REQUEST_THRESHOLD_MS = 3000;
/**
* 默认ByteArrayPool的大小
* 现在只需要知道ByteArrayPool.java是Volley用来从输入流中读取数据并将其转换成字节数组的工具即可
* 在这篇博客后面会介绍,表担心~= =
*/
private static int DEFAULT_POOL_SIZE = 4096;
/**
* 网络请求的真正接口
* 为什么这么说咧,BasicNetwork里面的performRequest()函数
* 调用了HttpStack里的performRequest(),真正的网络请求还是通过HttpStack里面的方法实现的
* 在Volley中实现了HttpStack接口的类有两个 HurlStack.java和HttpClientStack.java
* 针对了不同Android系统版本,用不同的方法实现了请求。
*/
protected final HttpStack mHttpStack;
//表急,后面会介绍到的,现在知道是一个用于数据转换的工具类就好了
protected final ByteArrayPool mPool;
/**
* @param httpStack HTTP stack to be used
* 传入的HttpStack实现类引用
* 整个网络请求的较核心部分就在HttpStack实现类上面咯
*/
public BasicNetwork(HttpStack httpStack) {
// If a pool isn't passed in, then build a small default pool that will give us a lot of
// benefit and not use too much memory.
this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE));
}
/**
* @param httpStack HTTP stack to be used
* @param pool a buffer pool that improves GC performance in copy operations
* Volley接口分离的很明显,而且在构造函数里面也提供了很多种
* 可以定制出适合自己的ByteArrayPool衍生类
* 当然也可以自己来实现HttpStack的衍生类
*/
public BasicNetwork(HttpStack httpStack, ByteArrayPool pool) {
mHttpStack = httpStack;
mPool = pool;
}
/**
* 这个方法重写的是Network的方法
* 在这个里面再调用HttpStack里面的performRequest方法
*/
@Override
public NetworkResponse performRequest(Request> request) throws VolleyError {
/**
* Returns milliseconds since boot, including time spent in sleep.
* 为了方便计算每个request所用的时间
* 在处理每个request之前都记下此刻unix时间戳
*/
long requestStart = SystemClock.elapsedRealtime();
/**
* 进入死循环= =
* 还没弄清楚为什么要死循环
*/
while (true) {
/**
* 指向HttpResponse实例的引用
* 是调用HttpStack方法performRequest()之后返回的结果
*/
HttpResponse httpResponse = null;
/**
* 返回的HttpResponse还需要经过处理
* 并不是返回回来就是能直接使用的数据
* 需要通过上面的ByteArrayPool将Entity转换成byte[]
* 这个就是指向解析后的byte[]的
*/
byte[] responseContents = null;
//用来存放response里面header的信息,包含了状态码等
Map responseHeaders = Collections.emptyMap();
try {
/**
* Gather headers.
* 设置header
* 从缓存中收集上次相同request的信息
*/
Map headers = new HashMap();
/**
* 将缓存的信息加入到headers中
* headers会跟随request一起发送给服务器
* 在函数的定义处会讲解
*/
addCacheHeaders(headers, request.getCacheEntry());
/**
* 通过调用HttpStack接口的performRequest()方法
* 获取服务器返回的HttpResponse
*/
httpResponse = mHttpStack.performRequest(request, headers);
/**
* The first line of a Response message is the Status-Line,
* consisting of the protocol version followed by a numeric status code and its associated textual phrase
* with each element separated by SP characters.
* No CR or LF is allowed except in the final CRLF sequence.
* 请求返回的response第一行就是包含了状态码的一行
*/
StatusLine statusLine = httpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
/**
* 将头部解析成键值对的形式再返回
*/
responseHeaders = convertHeaders(httpResponse.getAllHeaders());
/**
* Handle cache validation.
* 处理缓存信息
* 如果返回的状态码是304(HttpStatus.SC_NOT_MODIFIED)
* 则进行如下的处理
*/
if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
/**
* 如果缓存为空的话
* 那就说明该请求的返回的response的body就是null
* 直接构造一个NetworkResponse返回
*/
Entry entry = request.getCacheEntry();
if (entry == null) {
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, null,
responseHeaders, true,
SystemClock.elapsedRealtime() - requestStart);
}
// A HTTP 304 response does not have all header fields. We
// have to use the header fields from the cache entry plus
// the new ones from the response.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
/**
* 一个返回码为304的HttpResponse的header缺少一些信息
* 需要我们将cache中的一些header信息加入到其中
* 这样组成一个完整的NetworkResponse返回
*/
entry.responseHeaders.putAll(responseHeaders);
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data,
entry.responseHeaders, true,
SystemClock.elapsedRealtime() - requestStart);
}
/**
* Handle moved resources
* 处理了重定向的问题
* 并将request的mRedirectUrl设定成了新的url
*/
if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
String newUrl = responseHeaders.get("Location");
request.setRedirectUrl(newUrl);
}
/**
* Some responses such as 204s do not have content. We must check.
* 204(无内容)服务器成功处理了请求,但没有返回任何内容。
*
*/
if (httpResponse.getEntity() != null) {
/**
* 如果entity不为Null
* 将其转换成byte数组
* 利用之前提到过的ByteArrayPool.java类
*/
responseContents = entityToBytes(httpResponse.getEntity());
} else {
// Add 0 byte response as a way of honestly representing a
// no-content request.
responseContents = new byte[0];
}
/**
* if the request is slow, log it.
* 获取request已经占用的时间(requestLifetime)
* 判断是否需要打出request的超时状态
*/
long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
logSlowRequests(requestLifetime, request, responseContents, statusLine);
/**
* 如果状态码位于200之下或者是299之上(200-299 用于表示请求成功)
* 则抛出IOException异常= =为什么非要抛出这个异常
* 在前面过滤掉了(304等情况)
*/
if (statusCode < 200 || statusCode > 299) {
throw new IOException();
}
/**
* 经过上面的层层过滤
* 最后留下了200~299之间的请求成功response
* 通过HttpResponse里面的信息构造出一个volley自己封装的NetworkResponse对象
*/
return new NetworkResponse(statusCode, responseContents, responseHeaders, false,
SystemClock.elapsedRealtime() - requestStart);
/**
* 抛出了异常之后,会用attemptREtryOnException()方法来尝试retry
* 主要做的工作就是看是否还有retry的机会,如果有则不停通过这个死循环
* 进行请求,直到请求成功或者请求的机会用完为止
*/
} catch (SocketTimeoutException e) {
attemptRetryOnException("socket", request, new TimeoutError());
} catch (ConnectTimeoutException e) {·
attemptRetryOnException("connection", request, new TimeoutError());
} catch (MalformedURLException e) {
throw new RuntimeException("Bad URL " + request.getUrl(), e);
} catch (IOException e) {
/**
* 状态码在0~200以及299之上的response
* 处理的套路
*/
int statusCode = 0;
NetworkResponse networkResponse = null;
if (httpResponse != null) {
statusCode = httpResponse.getStatusLine().getStatusCode();
} else {
//如果状态码为0,则抛出NoConnectionError
throw new NoConnectionError(e);
}
/**
* 如果有重定向的情况发生
* 用log打出
*/
if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY ||
statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
VolleyLog.e("Request at %s has been redirected to %s", request.getOriginUrl(), request.getUrl());
} else {
VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
}
/**
* 如果返回的content内容不为Null
* 则构造出一个NetworkResponse
* 否则抛出NetworkError
*/
if (responseContents != null) {
networkResponse = new NetworkResponse(statusCode, responseContents,
responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
/**
* 抛出了异常之后,会用attemptREtryOnException()方法来尝试retry
* 主要做的工作就是看是否还有retry的机会,如果有则不停通过这个死循环
* 进行请求,直到请求成功或者请求的机会用完为止
*/
if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
statusCode == HttpStatus.SC_FORBIDDEN) {
attemptRetryOnException("auth",
request, new AuthFailureError(networkResponse));
} else if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY ||
statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
attemptRetryOnException("redirect",
request, new AuthFailureError(networkResponse));
} else {
// TODO: Only throw ServerError for 5xx status codes.
throw new ServerError(networkResponse);
}
} else {
throw new NetworkError(networkResponse);
}
}
}
}
/**
* Logs requests that took over SLOW_REQUEST_THRESHOLD_MS to complete.
* 如果request用时超出了预先设定的阀值
* 则打出log用于debug时候的提示
*/
private void logSlowRequests(long requestLifetime, Request> request,
byte[] responseContents, StatusLine statusLine) {
if (DEBUG || requestLifetime > SLOW_REQUEST_THRESHOLD_MS) {
VolleyLog.d("HTTP response for request=<%s> [lifetime=%d], [size=%s], " +
"[rc=%d], [retryCount=%s]", request, requestLifetime,
responseContents != null ? responseContents.length : "null",
statusLine.getStatusCode(), request.getRetryPolicy().getCurrentRetryCount());
}
}
/**
* Attempts to prepare the request for a retry. If there are no more attempts remaining in the
* request's retry policy, a timeout exception is thrown.
* 每次尝试都会使retry机会减少1,如果机会没有了,则抛出请求超时的exception
*
* @param request The request to use.
*/
private static void attemptRetryOnException(String logPrefix, Request> request,
VolleyError exception) throws VolleyError {
RetryPolicy retryPolicy = request.getRetryPolicy();
int oldTimeout = request.getTimeoutMs();
try {
retryPolicy.retry(exception);
} catch (VolleyError e) {
request.addMarker(
String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout));
throw e;
}
request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout));
}
/**
* 添加上缓存的header
* 如果有之前的缓存的信息
* 将里面的信息取出放入header中
*
* 这里面涉及到了一个条件请求
* 如果有缓存的话,header上面会带上一个If-Modified-Since关键字
* 服务器会先比较信息modified的时间,如果服务端的数据没有发生变化就返回304(也就是上面的 HttpStatus.SC_NOT_MODIFIED)
* 如果服务器的数据发生了变化,则会返回状态码200以及请求需要的数据(意思就是本地的数据需要刷新了,缓存不管用了)
*/
private void addCacheHeaders(Map headers, Cache.Entry entry) {
// If there's no cache entry, we're done.
if (entry == null) {
return;
}
if (entry.etag != null) {
headers.put("If-None-Match", entry.etag);
}
if (entry.lastModified > 0) {
Date refTime = new Date(entry.lastModified);
headers.put("If-Modified-Since", DateUtils.formatDate(refTime));
}
}
protected void logError(String what, String url, long start) {
long now = SystemClock.elapsedRealtime();
VolleyLog.v("HTTP ERROR(%s) %d ms to fetch %s", what, (now - start), url);
}
/**
* Reads the contents of HttpEntity into a byte[].
* 从HttpEntity中读取数据,并通过ByteArrayPool将其转换成byte[]
* 暂时不用管太多= =,等后面介绍到ByteArrayPool.java的时候就会明白
*/
private byte[] entityToBytes(HttpEntity entity) throws IOException, ServerError {
PoolingByteArrayOutputStream bytes =
new PoolingByteArrayOutputStream(mPool, (int) entity.getContentLength());
byte[] buffer = null;
try {
InputStream in = entity.getContent();
if (in == null) {
throw new ServerError();
}
/**
* 获取一个大小为1024的缓冲区
*/
buffer = mPool.getBuf(1024);
int count;
//将content的内容通过流每次最大读出1024个byte, 全部读出并写入bytes
while ((count = in.read(buffer)) != -1) {
bytes.write(buffer, 0, count);
}
return bytes.toByteArray();
} finally {
try {
// Close the InputStream and release the resources by "consuming the content".
entity.consumeContent();
} catch (IOException e) {
// This can happen if there was an exception above that left the entity in
// an invalid state.
VolleyLog.v("Error occured when calling consumingContent");
}
/**
* 在所有工作完成之后
* 需要将从mPool中拿出的buffer缓冲区回收
*/
mPool.returnBuf(buffer);
bytes.close();
}
}
/**
* Converts Headers[] to Map.
* 将返回的response里面的header[]
* 全部转换成Map里面的键值对形式
*/
protected static Map convertHeaders(Header[] headers) {
Map result = new TreeMap(String.CASE_INSENSITIVE_ORDER);
for (int i = 0; i < headers.length; i++) {
result.put(headers[i].getName(), headers[i].getValue());
}
return result;
}
}
ByteArrayPool.java是用来将HttpResponse中Entity通过stream的形式转换成byte[],主要的作用是提供缓冲区,用来辅助流数据的读取,在使用完成之后需要将使用过的缓冲区还给ByteArrayPool,ByteArrayPool里会对这些byte[]进行简单的回收处理。
/**
* 用来给外界提供byte[]作为缓冲区的一个工具类
*/
public class ByteArrayPool {
/**
* The buffer pool, arranged both by last use and by buffer size
*/
private List mBuffersByLastUse = new LinkedList();
private List mBuffersBySize = new ArrayList(64);
/**
* The total size of the buffers in the pool
* 缓冲池的当前大小
*/
private int mCurrentSize = 0;
/**
* The maximum aggregate size of the buffers in the pool. Old buffers are discarded to stay
* under this limit.
* 缓冲池当前的大小的阀值
* 超过了该值则会对缓冲池进行回收处理
*/
private final int mSizeLimit;
/**
* Compares buffers by size
* 比较两个缓冲区的大小的规则
* 如果返回一个负数,则表示前一个数要小
* 如果返回0,则表示两个数字相等
* 如果返回一个正数,则表示后一个数要小
*
*/
protected static final Comparator BUF_COMPARATOR = new Comparator() {
@Override
public int compare(byte[] lhs, byte[] rhs) {
return lhs.length - rhs.length;
}
};
/**
* @param sizeLimit the maximum size of the pool, in bytes
* 用来修改缓冲池的大小阀值
*/
public ByteArrayPool(int sizeLimit) {
mSizeLimit = sizeLimit;
}
/**
* Returns a buffer from the pool if one is available in the requested size, or allocates a new
* one if a pooled one is not available.
* 从mBuffersBySize中调出一个缓冲区来
* 如果大小符合要求,则直接返回给调用者
* 如果没有符合要求的,直接创建一个新的byte[]返回
*
* @param len the minimum size, in bytes, of the requested buffer. The returned buffer may be
* larger.
* @return a byte[] buffer is always returned.
*/
public synchronized byte[] getBuf(int len) {
for (int i = 0; i < mBuffersBySize.size(); i++) {
byte[] buf = mBuffersBySize.get(i);
if (buf.length >= len) {
mCurrentSize -= buf.length;
mBuffersBySize.remove(i);
mBuffersByLastUse.remove(buf);
return buf;
}
}
return new byte[len];
}
/**
* Returns a buffer to the pool, throwing away old buffers if the pool would exceed its allotted
* size.
*
* @param buf the buffer to return to the pool.
*/
public synchronized void returnBuf(byte[] buf) {
//如果buf为空或者超出了规定的大小,不管就行了,这种缓冲区用不着回收,因为= =根本就不符合要求嘛
if (buf == null || buf.length > mSizeLimit) {
return;
}
//如果buf符合要求,则将其加入到最近使用的队列中去
mBuffersByLastUse.add(buf);
/**
* 通过二分查找,比较规则为BUF_COMPARATOR,找出新进来的buf应该处于的位置
* 随后将buf插入到mBufferBySize的队列里面
*/
int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR);
if (pos < 0) {
pos = -pos - 1;
}
mBuffersBySize.add(pos, buf);
//当前总缓冲区大小变大
mCurrentSize += buf.length;
//对整个缓冲池的大小做出调整
trim();
}
/**
* Removes buffers from the pool until it is under its size limit.
* 调整缓冲区的大小
* 直到mCurrentSize在限制大小之下
*/
private synchronized void trim() {
while (mCurrentSize > mSizeLimit) {
byte[] buf = mBuffersByLastUse.remove(0);
mBuffersBySize.remove(buf);
mCurrentSize -= buf.length;
}
}
}
在BasicNetwork.java这个类中,通过死循环加上try,catch的方式,不停的对一个request进行重复的处理,里面涉及到了RetryPolicy.java
接口以及其默认实现类,这个接口是用来专门处理一个request在发送以及得到服务器响应返回结果的过程中出现的问题。通过有限次数的不断扩大request响应时间阀值,再次发送request的方式来达到一个retry的目的。和Network.java
类似的,RetryPolicy.java
也仅仅就是提供了抽象方法,想把具体的实现内容弄明白还需要去默认实现类DefaultRetryPolicy.java
中去。
package com.android.volley;
/**
* Retry policy for a request.
* 该类用来管理request的调整及重新发送
* 所谓调整就是将request响应时间(timeout)放宽
*/
public interface RetryPolicy {
/**
* Returns the current timeout (used for logging).
*/
public int getCurrentTimeout();
/**
* Returns the current retry count (used for logging).
*/
public int getCurrentRetryCount();
/**
* Prepares for the next retry by applying a backoff to the timeout.
* 为下一次request做好准备,通过不停地来放宽timeout时间限制
* 在DefaultRetryPolicy.java中好理解一些
*
* @param error The error code of the last attempt.
* @throws VolleyError In the event that the retry could not be performed (for example if we
* ran out of attempts), the passed in error is thrown.
*/
public void retry(VolleyError error) throws VolleyError;
}
DefaultRetryPolicy.java
描述了对待Volley中涉及Network的request的策略方针,可以理解为重试策略方针,也就是对那些在网络请求失败的request处理方法。里面包含了retry的最大次数(mMaxNumRetries
),当前请求次数(mCurrentRetryCount
)以及请求超时的时间阀值(mCurrentTimeoutMs
)等。每个Request里面都包含了一个RetryPolicy.java
实现类,在处理的时候可以通过getRetryPolicy()
方法获得。
package com.android.volley;
/**
* Default retry policy for requests.
*/
public class DefaultRetryPolicy implements RetryPolicy {
/**
* The current timeout in milliseconds.
* 请求超时的时间数
*/
private int mCurrentTimeoutMs;
/**
* The current retry count.
* 当前请求的重试次数
*/
private int mCurrentRetryCount;
/**
* The maximum number of attempts.
* 重复尝试的最大次数
**/
private final int mMaxNumRetries;
/**
* The backoff multiplier for the policy.
* 暂时不明白这个有什么用
* 根据后面的来看好像是一个用于放宽timeout时间限制的系数
* 这个系数越大每次retry的时候放宽的程度也就越大
*/
private final float mBackoffMultiplier;
/** The default socket timeout in milliseconds */
public static final int DEFAULT_TIMEOUT_MS = 2500;
/** The default number of retries */
public static final int DEFAULT_MAX_RETRIES = 0;
/** The default backoff multiplier */
public static final float DEFAULT_BACKOFF_MULT = 1f;
/**
* Constructs a new retry policy using the default timeouts.
* 默认的构造器,2.5s的超时,
* 最大重试数为0,也就是request请求超时了就不要再自动重试了
*/
public DefaultRetryPolicy() {
this(DEFAULT_TIMEOUT_MS, DEFAULT_MAX_RETRIES, DEFAULT_BACKOFF_MULT);
}
/**
* Constructs a new retry policy.
* @param initialTimeoutMs The initial timeout for the policy.
* @param maxNumRetries The maximum number of retries.
* @param backoffMultiplier Backoff multiplier for the policy.
*/
public DefaultRetryPolicy(int initialTimeoutMs, int maxNumRetries, float backoffMultiplier) {
mCurrentTimeoutMs = initialTimeoutMs;
mMaxNumRetries = maxNumRetries;
mBackoffMultiplier = backoffMultiplier;
}
/**
* Returns the current timeout.
*/
@Override
public int getCurrentTimeout() {
return mCurrentTimeoutMs;
}
/**
* Returns the current retry count.
*/
@Override
public int getCurrentRetryCount() {
return mCurrentRetryCount;
}
/**
* Returns the backoff multiplier for the policy.
*/
public float getBackoffMultiplier() {
return mBackoffMultiplier;
}
/**
* Prepares for the next retry by applying a backoff to the timeout.
* 该方法定义在RetryPolicy.java中。
* 为下一次重试request做准备,好像是通过延长服务器响应时间的限制 = =
* 每次对timeout的时间限制都放宽了mBackoffMultiplier个单位。让服务器多一点时间去响应
*
* @param error The error code of the last attempt.
* 最后一次request服务器给出的错误码
*/
@Override
public void retry(VolleyError error) throws VolleyError {
mCurrentRetryCount++;
mCurrentTimeoutMs += (mCurrentTimeoutMs * mBackoffMultiplier);
if (!hasAttemptRemaining()) {
throw error;
}
}
/**
* Returns true if this policy has attempts remaining, false otherwise.
* 这个是用来判断是否还有retry机会的
*/
protected boolean hasAttemptRemaining() {
return mCurrentRetryCount <= mMaxNumRetries;
}
}
到这里对Network.java
接口以及RetryPolicy.java
接口的代码就分析完了,现在是清楚了在NetworkDispatcher.java
调用了mNetwork.performRequest()
之后发生了什么事情,还弄清楚了request在网络请求发送之后,出现了各种问题会怎么处理(重试策略),但还不知道最核心的网络请求是如何发生的,也就是在BasicNetwork.java
中的下面这行代码。
httpResponse = mHttpStack.performRequest(request, headers);
这行代码就涉及到了后面的HttpStack.java
接口及其两个实现类了,在下篇博客会对源代码进行逐句的分析。今天的分析就到这里咯~~~~,有什么不对的地方还望各juju指出,小达一定改正。