[关闭]
@946898963 2018-05-18T04:09:31.000000Z 字数 2685 阅读 978

Volley-NetworkResponse源码解析

Android控件跟框架 Android源码分析


BasicNetwork使用HttpStack执行网络请求,成功后返回一个NetworkResponse,NetworkResponse只是一个简单的记录状态码,body,响应头,服务端是否返回304并且缓存过,执行网络请求时间的类。

NetworkResponse源码如下所示:

  1. public class NetworkResponse {
  2. public final int statusCode;
  3. public final byte[] data;
  4. public final Map<String, String> headers;
  5. public final boolean notModified;
  6. public final long networkTimeMs;
  7. public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers,
  8. boolean notModified, long networkTimeMs) {
  9. this.statusCode = statusCode;
  10. this.data = data;
  11. this.headers = headers;
  12. this.notModified = notModified;
  13. this.networkTimeMs = networkTimeMs;
  14. }
  15. public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers,
  16. boolean notModified) {
  17. this(statusCode, data, headers, notModified, 0);
  18. }
  19. public NetworkResponse(byte[] data) {
  20. this(HttpStatus.SC_OK, data, Collections.<String, String>emptyMap(), false, 0);
  21. }
  22. public NetworkResponse(byte[] data, Map<String, String> headers) {
  23. this(HttpStatus.SC_OK, data, headers, false, 0);
  24. }
  25. }

成员变量

这里重点介绍下,notModified的值什么时候为true。当我们的Request允许使用缓存的时候,会先将Request放入到缓存请求队列中。缓存线程会从缓存请求队列中取出Request,然后去本地查找缓存,如果查找到缓存,但是缓存过期的话,会将本地的缓存数据(首部数据和实体数据)添加到Request中,然后将Request放入请求队列中,交由请求线程处理。

CacheDispatcher的run方法:

  1. @Override
  2. public void run() {
  3. ....
  4. while (true) {
  5. try {
  6. ....
  7. Cache.Entry entry = mCache.get(request.getCacheKey());
  8. if (entry == null) {
  9. request.addMarker("cache-miss");
  10. // Cache miss; send off to the network dispatcher.
  11. mNetworkQueue.put(request);
  12. continue;
  13. }
  14. if (entry.isExpired()) {
  15. request.addMarker("cache-hit-expired");
  16. request.setCacheEntry(entry);
  17. mNetworkQueue.put(request);
  18. continue;
  19. }
  20. ....
  21. }
  22. }

请求线程会从请求队列中取出Request,在发起请求之前,会检查Request中是否带有缓存数据(首部数据和实体数据),如果有的话会在设置请求首部的map中添加"If-None-Match"首部和"If-Modified-Since"首部,这两个首部是用来发起条件请求的,这两个首部的值分别为缓存数据中的etag和lastModified的值。

BasicNetwork的performRequest方法:

  1. @Override
  2. public NetworkResponse performRequest(Request<?> request) throws VolleyError {
  3. long requestStart = SystemClock.elapsedRealtime();
  4. while (true) {
  5. ....
  6. Map<String, String> headers = new HashMap<String, String>();
  7. addCacheHeaders(headers, request.getCacheEntry());
  8. httpResponse = mHttpStack.performRequest(request, headers);
  9. ....
  10. }
  11. }
  12. private void addCacheHeaders(Map<String, String> headers, Cache.Entry entry) {
  13. if (entry == null) {
  14. return;
  15. }
  16. if (entry.etag != null) {
  17. headers.put("If-None-Match", entry.etag);
  18. }
  19. if (entry.lastModified > 0) {
  20. Date refTime = new Date(entry.lastModified);
  21. headers.put("If-Modified-Since", DateUtils.formatDate(refTime));
  22. }
  23. }

最终包含在请求首部的map中的首部数据,会被设置到HttpUrlConnection中去,这样发起的请求就是条件请求了。

当发起条件请求的时候,如果服务器端没有符合条件的数据(在Volley中就是数据在某个时间点后并没有发生修改),这个时候会返回304状态码,这个时候构建NetworkResponse的时候,传入的notModified的值为true,这时候NetworkResponse中的数据实体部分使用的就是本地的缓存数据。

构造方法

构造方法就是对成员变量进行赋值。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注