zoukankan      html  css  js  c++  java
  • Android-Universal-Image-Loader学习笔记(一个)

    Android-Universal-Image-Loader它是一个开源项目,处理图像加载和缓存。闲暇的时候,读一些源。特别记录。

    所述图像文件(磁盘)高速缓存,我们需要考虑的因素,如以下

    1)  定义高速缓存文件的名称

    2)  缓存的大小

    3)  缓存文件的方式:比方限时保存文件等。图片压缩后的格式。压缩率等等。

    该项目对磁盘缓存保存文件时对文件名的改动也做了支持:在缓存文件时对文件名的改动提供了两种方式。每一种方式相应了一个Java类

    1)  HashCodeFileNameGenerator,该类负责获取文件名的hashcode然后转换成字符串。

    2)  Md5FileNameGenerator,该类把源文件的名称同过md5加密后保存。

    两个类都继承了FileNameGenerator接口

    它们之间的关系例如以下图所看到的

    在DefaultConfigurationFactory类中提供了一个工厂方法createFileNameGenerator。该方法返回了一个默认的FileNameGenerator对象:HashCodeFileNameGenerator.

    public static FileNameGenerator createFileNameGenerator() {
    		return new HashCodeFileNameGenerator();
    	}
    

    以下说说磁盘缓存的详细实现:

        首先定义了DiscCacheAware接口,该接口提供了例如以下方法

    方法名

    说明

    返回值

    getFileDectory()

    返回磁盘缓存的根文件夹

    File

    get(String imageUri)

    依据uri从缓存中获取图片

    File

    save(imageUri,InputStream iamgeStream,IoUtils.CopyListener listener)

    把图片保存在磁盘缓存上

    boolean

    save(imageUri,Bitmap bitmap)

    保存bitMap对象到磁盘缓存上

    Boolean

    remove(imageUri)

    依据imageUri删除文件

    boolean

    close()

    关闭磁盘缓存,释放资源

    void

    clear()

    清空磁盘缓存

    void

     然后定义了另外一个没方法的接口DiskCache(这个接口名称应该命名为DiscCache比較好)。该接口仅仅是简单的继承了DiscCacheAware接口

     BaseDiscCache实现了DiskCache,该类是个抽象类(定义为抽象类的优点之中的一个就是不是必需所有重写DiskCacheAware接口提供的方法),该类定义了磁盘缓冲区的下面的(默认)属性:

    1)  默认的缓存大小为32k

    2)  默认压缩后的图片格式为PNG(作为Bitmap的compress方法的第一个參数)

    3)  默认压缩后图片显示的质量为100,也就是压缩率为0,不进行压缩(作为compress的第二个參数)

    当然该类也提供了改动压缩图片格式和压缩率以及改动缓存大小的set方法。

    同一时候该类还封装了下面三个属性

    protected final File cacheDir;//缓存文件的保存Directory
    protected final File reserveCacheDir;//后备缓存的Diectory,当cacheDir不存在的情况下就是用reserveCahceDir后备缓存
    protected final FileNameGenerator fileNameGenerator;//文件名称名称生成器
    

    该类提供了三个构造函数

    1)  仅仅有一个參数的构造函数仅仅初始化了cacheDir。没实用到后备缓存。且是以HashCodeFileNameGenerator来生成目标文件的文件名称。

    2)  两个參数的构造器除了cacheDir和HashCodefileNameGenerator外,也能够初始化后备缓存

    3)  三个參数的构造器要求必须初始化cacheDir而且必须初始化filenNameGenerator否则就报异常

    三个构造器的代码例如以下

    public BaseDiscCache(File cacheDir) {
    		this(cacheDir, null);
    	}
    public BaseDiscCache(File cacheDir, File reserveCacheDir) {
    		this(cacheDir, reserveCacheDir, DefaultConfigurationFactory.createFileNameGenerator());
    	}
    
    	public BaseDiscCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator) {
    		if (cacheDir == null) {
    			throw new IllegalArgumentException("cacheDir" + ERROR_ARG_NULL);
    		}
    		if (fileNameGenerator == null) {
    			throw new IllegalArgumentException("fileNameGenerator" + ERROR_ARG_NULL);
    		}
    
    		this.cacheDir = cacheDir;
    		this.reserveCacheDir = reserveCacheDir;
    		this.fileNameGenerator = fileNameGenerator;
    	}
    

    BasicDiscCache实现了除close之外的其余的六个方法,以下进行一一说明:

    1)      clear():循环便利cacheDir.listFiles()的每个File对象。然后调用File对象的delete()方法来清空缓存

    2)      getDirectory():直接返回了cacheDir

    3)      get(StringimageUri):该方法调用BasicCahce的一个重要方法getFile(String imageUri).

    该方法例如以下所看到的(该方法在save方法中也有调用)

    protected File getFile(String imageUri) {
    		String fileName = fileNameGenerator.generate(imageUri);
    		File dir = cacheDir;
    		if (!cacheDir.exists() && !cacheDir.mkdirs()) {
    			if (reserveCacheDir != null && (reserveCacheDir.exists() || reserveCacheDir.mkdirs())) {
    				dir = reserveCacheDir;
    			}
    		}
    		return new File(dir, fileName);
    	}

    4)      save(StringimageUri, Bitmap bitmap)方法的详细实现

    public boolean save(String imageUri, Bitmap bitmap) throws IOException {
    		//获取imageUri的File对象,该对象封装了缓存路径和图片保存后的名称
    		File imageFile = getFile(imageUri);
    		//获取暂时保存文件的tmpFile对象
    		File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX);
    		
    		OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize);
    		boolean savedSuccessfully = false;
    		try {
    			//调用compress把bitMap压缩到tempFile中
    			savedSuccessfully = bitmap.compress(compressFormat, compressQuality, os);
    		} finally {
    			IoUtils.closeSilently(os);
    			//假设保存成功而且tempFile的文件没有成功移动到imageFile的话。就删除temFile
    			if (savedSuccessfully && !tmpFile.renameTo(imageFile)) {
    				savedSuccessfully = false;
    			}
    			if (!savedSuccessfully) {
    				tmpFile.delete();
    			}
    		}
    		//对bitmap进行垃圾回收
    		bitmap.recycle();
    		return savedSuccessfully;
    	}
    

    5)save的另外一个重载方法处理的逻辑同上,须要注意的是两个save方法当文件保存时会先生成一个tempFile然后会将调用renameTo方法将该tempFile重命名为imageFile

    BaseDiscCache有两个扩展类,一个是不限制缓存大小的UnlimitedDiscCache和限制缓存时间的LimitedAgeDiscCache当中UnlimitedDiscCache非常easy它仅仅是简单的继承了BaseDiscCache并未对BaseDiscCache做不论什么扩展。

    LimitedAgeDiscCache该类实现了在缓存中删除被载入超过规定时间的文件:满足下面条件的时候就从缓存中删除文件:系统当前时间-文件的最新改动时间》maxFileAge

    该类提供了两个属性:

    1.  maxFileAge(long类型)设置载入的超时的最大时间,改时间在构造器冲初始化。一经初始化就不能改变(设定文件存活的最长时间,当超过这个值,就删除该文件)

    2.  loadingDates (Map<File,long>),该属性是一个map类型的对象,key保存的要缓存的图片文件,而value保存的是调用save方法是系统的当前时间。详细向loadingDates填充数据是在以下的rememberUsage方法中实现的,该方法在类中两个save方法中调用,首先调用父类的save方法,然后在调用此方法

    	private void rememberUsage(String imageUri) {
    		File file = getFile(imageUri);
    		long currentTime = System.currentTimeMillis();
    		file.setLastModified(currentTime);
    		loadingDates.put(file, currentTime);
    	}

    从缓存中获取数据的方法为get(String imageUri)该类是重写BaseDiscDache方法。该方法从loadingDates中获取imageUri所代表的图片的最新更新时间loadingDate,然后拿当前时间和loadingDate做差。假设差值大于maxFileAge也就是说查过了载入的最大时间,就删除该imageUri所代表的file,并从loadingDates中的数据。当然假设map中没有imageUri就不会涉及到超时的问题,此时就把image放入map中去,详细的实现例如以下

    @Override
    	public File get(String imageUri) {
    		File file = super.get(imageUri);
    		if (file != null && file.exists()) {
    			boolean cached;
    			Long loadingDate = loadingDates.get(file);
    			if (loadingDate == null) {
    				cached = false;
    				loadingDate = file.lastModified();
    			} else {
    				cached = true;
    			}
    
    			if (System.currentTimeMillis() - loadingDate > maxFileAge) {
    				file.delete();
    				loadingDates.remove(file);
    			} else if (!cached) {
    				loadingDates.put(file, loadingDate);
    			}
    		}
    		return file;
    	}
    





    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    hook declined to update refs/heads/dev
    关于OC中的几种延迟执行方式
    .gitignore中添加的某个忽略文件并不生效
    ios实现fastlane自动化打包
    iOS根据图片url获取尺寸
    iOS保存图片到相册崩溃
    你真的会java吗
    安卓沉浸式状态栏
    安卓接入融云IM连接不上??
    springboot无法访问静态资源
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4658705.html
Copyright © 2011-2022 走看看