android volley缓存设计分析

本文学习一下volley的缓存设计写法。
首先看下哪些类使用了cache。
Cache.java
public interface Cache {
public Entry get(String key);
public void put(String key, Entry entry);
public void initialize();
public void invalidate(String key, boolean fullExpire);
public void remove(String key);
public void clear();
public static class Entry {
       /** The data returned from cache. */
       public byte[] data;
        /** ETag for cache coherency. */
       public String etag;
        /** Date of this response as reported by the server. */
       public long serverDate;
        /** The last modified date for the requested object. */
       public long lastModified;
        /** TTL for this record. */
       public long ttl;
        /** Soft TTL for this record. */
       public long softTtl;
        /** Immutable response headers as received from server; must be non-null. */
       public Map<String, String> responseHeaders = Collections.emptyMap();
        /** True if the entry is expired. */
       public boolean isExpired() {
           return this.ttl < System.currentTimeMillis();
       }
        /** True if a refresh is needed from the original data source. */
       public boolean refreshNeeded() {
           return this.softTtl < System.currentTimeMillis();
       }
   }
}

DiskBasedCache是唯一的实现类。
DiskBasedCache.java
public synchronized void initialize() {
   if (!mRootDirectory.exists()) {
       if (!mRootDirectory.mkdirs()) {
           VolleyLog.e("Unable to create cache dir %s", mRootDirectory.getAbsolutePath());
       }
       return;              //路径不存在则只需创建路径即可返回
   }

    File[] files = mRootDirectory.listFiles();
   if (files == null) {
       return;            //路径存在 但不存在子目录即可返回
   }
   for (File file : files) {
       BufferedInputStream fis = null;
       try {
           fis = new BufferedInputStream(new FileInputStream(file));
           CacheHeader entry = CacheHeader.readHeader(fis);
           entry.size = file.length();
           putEntry(entry.key, entry);    //若路径下的子路径不为空 则将子路径处理成cache
       } catch (IOException e) {
           if (file != null) {
              file.delete();
           }
       } finally {
           try {
               if (fis != null) {
                   fis.close();
               }
          } catch (IOException ignored) { }
       }
   }
}

private void putEntry(String key, CacheHeader entry) {
   if (!mEntries.containsKey(key)) {
       mTotalSize += entry.size;
   } else {
       CacheHeader oldEntry = mEntries.get(key);
       mTotalSize += (entry.size - oldEntry.size);
   }
   mEntries.put(key, entry);     //mEntries—>new LinkedHashMap<String,CacheHeader>(16,.75f,true);
                         //volley是这样做的 在内存中保留一个map 在硬盘中存储实际的内容
}

@Override
public synchronized void put(String key, Entry entry) {
   pruneIfNeeded(entry.data.length);
   File file = getFileForKey(key);
   try {
       BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(file));
       CacheHeader e = new CacheHeader(key, entry); //将除data外的信息保存到cacheHeader进而保存到map 内存
       boolean success = e.writeHeader(fos);                //将header信息写入硬盘
       if (!success) {
           fos.close();
           VolleyLog.d("Failed to write header for %s", file.getAbsolutePath());
           throw new IOException();
       }
       fos.write(entry.data);                                         //将data写入硬盘
       fos.close();
       putEntry(key, e);
       return;
   } catch (IOException e) {
   }
   boolean deleted = file.delete();
   if (!deleted) {
       VolleyLog.d("Could not clean up file %s", file.getAbsolutePath());
   }
}

看一个cache put行为的实例。
NetworkDispatcher.java
public void run()
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");
}

看一个Response实现parseNetworkResponse的例子。
ImageRequest.java
protected Response<Bitmap> parseNetworkResponse(NetworkResponse response)
return doParse(response);

private Response<Bitmap> doParse(NetworkResponse response)
return Response.success(bitmap, HttpHeaderParser.parseCacheHeaders(response));  
                   //由下面的接口知 第二个参数就是cache.Entry—>回忆一下 自定义GsonRequest最后也用到了这个
      //具体实现类HttpHeaderParser 在com.android.volley.toolbox包下 此处不做分析 就是构造出一个entry而已
     /******
Response.java
public static <T> Response<T> success(T result, Cache.Entry cacheEntry) {
   return new Response<T>(result, cacheEntry);
}
   *****///

回到DiskBasedCache.java
static class CacheHeader {
   public long size;                                              //观察到这些字段和Cache Entry是一样的 唯独少了data字段
    /** The key that identifies the cache entry. */
   public String key;
    /** ETag for cache coherence. */
   public String etag;
    /** Date of this response as reported by the server. */
   public long serverDate;
    /** The last modified date for the requested object. */
   public long lastModified;
    /** TTL for this record. */
   public long ttl;
    /** Soft TTL for this record. */
   public long softTtl;
    /** Headers from the response resulting in this cache entry. */
public Map<String, String> responseHeaders;  //观察到这些字段和Cache Entry是一样的 唯独少了data字段
public CacheHeader(String key, Entry entry);                    //构造函数
public static CacheHeader readHeader(InputStream is);   //读取header 其实是剔除文件中header部分的内容
public Entry toCacheEntry(byte[] data);                            //根据data还原出一个Entry对象
public boolean writeHeader(OutputStream os);                 //写header
}

最后看一下get的实现
@Override
public synchronized Entry get(String key) {
   CacheHeader entry = mEntries.get(key);
   // if the entry does not exist, return.
   if (entry == null) {
       return null;
   }

    File file = getFileForKey(key);
   CountingInputStream cis = null;
   try {
       cis = new CountingInputStream(new BufferedInputStream(new FileInputStream(file)));
       CacheHeader.readHeader(cis); // eat header
       byte[] data = streamToBytes(cis, (int) (file.length() - cis.bytesRead));
       return entry.toCacheEntry(data);
   } catch (IOException e) {
       VolleyLog.d("%s: %s", file.getAbsolutePath(), e.toString());
       remove(key);
       return null;
   }  catch (NegativeArraySizeException e) {
       VolleyLog.d("%s: %s", file.getAbsolutePath(), e.toString());
       remove(key);
       return null;
   } finally {
       if (cis != null) {
           try {
               cis.close();
           } catch (IOException ioe) {
               return null;
           }
       }
   }
}            //没啥特别

ok~这篇文章就先到这里啦~
这篇文章分析了volley关于cache的实现。
1 volley封装了一个Cache接口 用于操作cache比如插入cache 清除cache等
2 volley封装了的Cache.Entry实体用于保存cache实际的内容 比如cache中内容从服务器获取的时间 cache
  的内容等
3 为了构建cache.Entry实体 volley封装了一个HttpHeaderParser类 在http请求成功时将http请求 比如请求头 data封装成一个Cache.Entry。
4 volley为了加快cache的查找速度保存了一个类型为LinkedHashMap<String,CacheHeader>的变量保存在内容中。
5 volley再次封装Cache.Entry 封装出一个CacheHeader保存cache.Entry除data外的内容(这样可以作为map的value) 而将实际data存储在硬盘。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值