全面解析Android的开源图片框架Universal-Image-Loader

2019-12-10 18:34:04丽君

我们可以看到这个类中维护的是一个LinkedHashMap,在LruMemoryCache构造函数中我们可以看到,我们为其设置了一个缓存图片的最大值maxSize,并实例化LinkedHashMap, 而从LinkedHashMap构造函数的第三个参数为ture,表示它是按照访问顺序进行排序的,
我们来看将bitmap加入到LruMemoryCache的方法put(String key, Bitmap value),  第61行,sizeOf()是计算每张图片所占的byte数,size是记录当前缓存bitmap的总大小,如果该key之前就缓存了bitmap,我们需要将之前的bitmap减掉去,接下来看trimToSize()方法,我们直接看86行,如果当前缓存的bitmap总数小于设定值maxSize,不做任何处理,如果当前缓存的bitmap总数大于maxSize,删除LinkedHashMap中的第一个元素,size中减去该bitmap对应的byte数
我们可以看到该缓存类比较简单,逻辑也比较清晰,如果大家想知道其他内存缓存的逻辑,可以去分析分析其源码,在这里我简单说下FIFOLimitedMemoryCache的实现逻辑,该类使用的HashMap来缓存bitmap的弱引用,然后使用LinkedList来保存成功加入到FIFOLimitedMemoryCache的bitmap的强引用,如果加入的FIFOLimitedMemoryCache的bitmap总数超过限定值,直接删除LinkedList的第一个元素,所以就实现了先进先出的缓存策略,其他的缓存都类似,有兴趣的可以去看看。

硬盘缓存

接下来就给大家分析分析硬盘缓存的策略,这个框架也提供了几种常见的缓存策略,当然如果你觉得都不符合你的要求,你也可以自己去扩展

  • FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的文件)
  • LimitedAgeDiscCache(设定文件存活的最长时间,当超过这个值,就删除该文件)
  • TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的文件)
  • UnlimitedDiscCache(这个缓存类没有任何的限制)

    下面我们就来分析分析TotalSizeLimitedDiscCache的源码实现

    /******************************************************************************* 
     * Copyright 2011-2013 Sergey Tarasevich 
     * 
     * Licensed under the Apache License, Version 2.0 (the "License"); 
     * you may not use this file except in compliance with the License. 
     * You may obtain a copy of the License at 
     * 
     * http://www.easck.com/licenses/LICENSE-2.0 
     * 
     * Unless required by applicable law or agreed to in writing, software 
     * distributed under the License is distributed on an "AS IS" BASIS, 
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     * See the License for the specific language governing permissions and 
     * limitations under the License. 
     *******************************************************************************/ 
    package com.nostra13.universalimageloader.cache.disc.impl; 
     
    import com.nostra13.universalimageloader.cache.disc.LimitedDiscCache; 
    import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator; 
    import com.nostra13.universalimageloader.core.DefaultConfigurationFactory; 
    import com.nostra13.universalimageloader.utils.L; 
     
    import java.io.File; 
     
    /** 
     * Disc cache limited by total cache size. If cache size exceeds specified limit then file with the most oldest last 
     * usage date will be deleted. 
     * 
     * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) 
     * @see LimitedDiscCache 
     * @since 1.0.0 
     */ 
    public class TotalSizeLimitedDiscCache extends LimitedDiscCache { 
     
     private static final int MIN_NORMAL_CACHE_SIZE_IN_MB = 2; 
     private static final int MIN_NORMAL_CACHE_SIZE = MIN_NORMAL_CACHE_SIZE_IN_MB * 1024 * 1024; 
     
     /** 
      * @param cacheDir  Directory for file caching. <b>Important:</b> Specify separate folder for cached files. It's 
      *      needed for right cache limit work. 
      * @param maxCacheSize Maximum cache directory size (in bytes). If cache size exceeds this limit then file with the 
      *      most oldest last usage date will be deleted. 
      */ 
     public TotalSizeLimitedDiscCache(File cacheDir, int maxCacheSize) { 
      this(cacheDir, DefaultConfigurationFactory.createFileNameGenerator(), maxCacheSize); 
     } 
     
     /** 
      * @param cacheDir   Directory for file caching. <b>Important:</b> Specify separate folder for cached files. It's 
      *       needed for right cache limit work. 
      * @param fileNameGenerator Name generator for cached files 
      * @param maxCacheSize  Maximum cache directory size (in bytes). If cache size exceeds this limit then file with the 
      *       most oldest last usage date will be deleted. 
      */ 
     public TotalSizeLimitedDiscCache(File cacheDir, FileNameGenerator fileNameGenerator, int maxCacheSize) { 
      super(cacheDir, fileNameGenerator, maxCacheSize); 
      if (maxCacheSize < MIN_NORMAL_CACHE_SIZE) { 
       L.w("You set too small disc cache size (less than %1$d Mb)", MIN_NORMAL_CACHE_SIZE_IN_MB); 
      } 
     } 
     
     @Override 
     protected int getSize(File file) { 
      return (int) file.length(); 
     } 
    }