Volley 源码笔记(1)

134 篇文章 0 订阅
24 篇文章 0 订阅

Volley

  1. Volley主类很简单,只是一个工具类来提供建立新的RequestQueue, 而RequestQueue其实正是Volley的对外交互主体, HttpRequest的添加执行与取消都是通过对requestQueue的操作实现的. 所以RequestQueue才是真正的主角.

  2. newRequestQueue最简单的形式是只需要一个context, 然后会调用到newRequestQueue(context, null), 后者是newRequestQueue(Context context, HttpStack stack):

    • 因为volley会和http打交道,因此会有cache的存在,这个cache在这里是以文件夹的形式存在的, 一般这个cache文件夹也会在App的cache目录下(context.getCacheDir()),这个文件夹的目录名就是”volley”.
    • userAgent这个header会有一个默认值为”volley/0”, 不过会试图去获取App的packageName(context.getPackageName())以及PackageInfo(context.getPackageManager().getPackageInfo(packageName, 0)), 并且会拼接一个packagageName + info.version的字符串作为userAgent.
    • 如果传入的stack是null, 那么这里就会自己new一个stack(对于SDK>=9的情况,会使用HurlStack这个类), 基于这个stack可以构造一个BasicNetwork, 然后再用之前new的cache File对象构造一个DiskBasedCache, 和刚才构造的network一起作为构造参数构造一个RequestQueue.
    • 构造了RequestQueue以后,会直接将其start. 然后返回供调用者使用.
  3. HurlStack implements HttpStack:

    • HttpStack接口很简单,只有一个方法: HttpResponse performRequest(Request ? request, Map String, String additionalHeaders) throws IOException, AuthFailureError
    • HurlStack接受一个UrlRewriter和SSLSocketFactory作为构造参数, 并分别保存在mUrlRewriter和mSslSocketFactory.
    • UrlRewriter是内部定一个的一个接口,其作用也就是将originalUrl转换为合适的Url,在url不可用的情况下会返回null, UrlRewriter是hurlStack**对外的一个定制化的回调, 调用者可以自己实现这个类并加入自己的逻辑,mUrlRewriter这个对象不是必须的**
    • SSLSocketFactory则是在Java扩展包中提供的: javax.net.ssl.SSLSocketFactory. 这个类的作用它的名字已经解释的很清楚了.
    • performRequest(Request ? request, Map String, String additionalHeaders):
      • 先获得 request的url, 然后新建一个HashMap String, String.
      • 现将request的所有header添加到map中,再将additionalHeaders添加到map中.
      • 如果存在可用的mUrlRewriter,那么会用其对url进行预处理并将结果作为url.
      • 根据url构造出一个URL对象, 然后调用openConnection(parsedUrl, request)获得一个HttpURLConnection(java.net提供的)
      • 遍历之前的header map, 将map中的header都加入到connection中去connection.addRequestProperty(…..)
      • setConnectionParametersForRequest(…)会为connection设置参数.
      • new ProtocolVersion(“HTTP”, 1, 1)
      • 调用connection.getResponseCode()等待http请求返回并取得http的status code.
      • 如果response code是-1, 那么直接抛一个IOException告知不能从回复中提取出status code.
      • 利用ProtocolVersion结合connection的responsecode和response message得到一个StatusLine对象代表着这次回覆的内容的status line(响应消息的第一行是状态行(stauts-Line),由协议版本以及数字状态码和相关的文本短语组成,各部分间用空格符隔开,除了最后的回车或换行外,中间不允许有回车换行).
      • 再根据这个statusLine对象构造出一个BasicHttpResponse(apache库)
      • 上面构造的BasicHttpResponse**只包含了status line,没有 header也没有entity**,因此需要添加上后两者:
        • entity 通过 BasicHttpResponse的setEntity(entityFromConnection(connection))
        • header在而是遍历connection.getHeaderFields(), 根据每对键值构造一个BasicHeader并将其加入到BasicHttpResponse中去.
      • 最后返回一个已经将所有信息填入的BasicHttpResponse.
  4. HurlStack内部的几个函数:

    • openConnection(URL url, Request ? request):
      • url.openConnection()会得到一个HttpURLConnection, 然后获取request的timeout值(request.getTimeoutMs()), 将HttpURLConnection的connectTimeout和ReadTimeout都设为这个值.
      • connection.setUseCaches(false), 不使用自带的cache功能,volley自己实现.
      • connection.setDoInput(true),开启了才能获得回复的数据,默认其实就是true.
      • 如果url是https类型的,那么设置connection的setSSLSocketFactory为mSslSocketFactory.
    • setConnectionParametersForRequest(HttpURLConnection connection,
      Request ? request): 会根据request的http 请求类型进行不同的操作:
      Method是在Request中定义的
      • Method.DEPRECATED_GET_OR_POST: 这种情况是针对一个POST请求,但是其body为空的情况,这种情况,应该认为是一个GET, 否则都应该是POST, 会将connection的output打开,设置方法为POST, 并根据Request的getPostBodyContentType设置content-type这个header, 然后利用connection的getOutputStream()将postBody的信息写入然后close.
      • Method.GET/Method.DELETE/Method.HEAD/Method.OPTIONS/Method.TRACE: 这几个方法只是简单的将connection的setRequestMethod设置为对应的类型.
      • Method.POST:
      • Method.PUT:
      • Method.PATCH: 这三者都会有body,需要添加。
    • addBodyIfExists()操作其实和处理DEPRECATED_GET_OR_POST的一样.
  5. entityFromConnection(HttpURLConnection connection): 作用就是将connection的response body给抽取出来:

    • 先构造一个BasicHttpEntity对象entity.
    • 然后尝试获取connection的getInputStream(), 如果中间有IO异常,那么改为获取connection的getErrorStream()
    • 然后将entitysetContent设置为此stream.
    • 在设置contentLength/conetntEncoding/ContentType等信息.
  6. 可以看到这里的HurlStack工作流程也很简单,就是对http发起请求到返回的一个简单封装罢了,这里的stack代表的是http协议栈中”栈”, 而非其结构是stack.

  7. BasicNetwork implements Network:

    • Network接口很简单: 只有一个函数: NetworkResponse performRequest(Request ? request) throws VolleyError
    • BasicNetwork接受两个输入参数HttpStack(mHttpStack)和ByteArrayPool(一般自己会new一个yteArrayPool(DEFAULT_POOL_SIZE))
    • performRequest(Request ? request):
      • 每次开始之前会获取一下当前的时间: SystemClock.elapsedRealtime()并保存.
      • 然后是一个while(true)循环,网络交互的实现已经封装在了之前的HurlStack中,这里在requestheader中还会加入控制cache的header(根据之前的request来设置合适的header): addCacheHeaders(headers, request.getCacheEntry()).
      • 在HurlStack返回了请求结果以后,responseheader会做一次转化: convertHeaders(…),然后会对status code做分类处理:
        • SC_NOT_MODIFIED: 这种情况只有header被更新了,body直接用以前cache的就可以,会通过request.getCacheEntry()获取被cache的entry, 如果没有获取到,那么就直接将SC_NOT_MODIFIED原样返回让调用者自己处理, 否则就吧cache的entry返回,并将相应的responseheader更新.
        • 如果httpResponse的entity存在,但是也有可能是空的,这种情况也会将content设置为一个byte[0]代表为空.
        • 然后记录当前时间,和开始的时候进行比较,如果很慢,会把这次记录在log里.
        • 如果status code不是2XX, 那么直接抛出一个IOException(后面会catch住做进一步处理,这里的抛出只是一种代码流程设计逻辑)
        • 中间可能的异常有SocketTimeoutException/ ConnectTimeoutException, 这两种情况会进行重试, MalformedURLException在Url不仅合法的时候会发生,会直接继续throw一个RuntimeException(“Bad url”)来表示.
        • 对IOException的处理是先判断返回的httpResponse是不是null,如果是null,那么可以认为是NoConnectionError(e), 否则就获取到返回的status code,并在log里输出这个status code, 但是如果status code是SC_UNAUTHORIZED或者SC_FORBIDDEN, 那么会再次进行尝试附加auth,否则就直接抛出ServerError(networkResponse)(一个TODO在这里说以后会改为只对5XX的错误才抛出ServerError), 对于3XX这种没有考虑的原因应该是HttpUrlConnection会自动重定位, 其他的情况,都抛出NetworkError.
    • convertHeaders(Header[] headers)函数很简单,只是将Headr[]转化为Map,并且按照http协议中header的名称大小写不敏感,会将TreeMap也设置为String.CASE_INSENSITIVE_ORDER.
    • ttemptRetryOnException(…): 根据request的RetryPolicy进行retry的设置, 如果已经不能再重试了,那么会抛出一个VolleyError(注释讲).
    • entityToBytes(HttpEntity entity)就是将entity转化为一个byte数组. 这里用到了volley自定义的PoolingByteArrayOutputStream,可以节省内存.
    • 可以看出BasicNetwork也是一个简单的类,其主要工作是针对HurlStack得到的Http回复进行相应的操作以及一部分cache控制.
  8. Cache接口: 除了定义方法外,还定义了CacheEntry这个static类作为一个cache在内存中的数据结构.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值