Android-Universal-Image-Loader学习笔记(一个)
Android-Universal-Image-Loader它是一个开源项目,处理图像加载和缓存。闲暇的时候,读一些源。特别记录。
所述图像文件(磁盘)高速缓存,我们需要考虑的因素,如以下
1) 定义高速缓存文件的名称
2) 缓存的大小
3) 缓存文件的方式:比方限时保存文件等。图片压缩后的格式。压缩率等等。
该项目对磁盘缓存保存文件时对文件名的改动也做了支持:在缓存文件时对文件名的改动提供了两种方式。每一种方式相应了一个Java类
1) HashCodeFileNameGenerator,该类负责获取文件名的hashcode然后转换成字符串。
2) Md5FileNameGenerator,该类把源文件的名称同过md5加密后保存。
两个类都继承了FileNameGenerator接口
它们之间的关系例如以下图所看到的
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2h1bnFpdXdlaQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
在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;
}
版权声明:本文博客原创文章。博客,未经同意,不得转载。
Android-Universal-Image-Loader学习笔记(一个)的更多相关文章
- Android(java)学习笔记219:开发一个多界面的应用程序之两种意图
		
1.两种意图: (1)显式意图: 在代码里面用intent设置要开启Activity的字节码.class文件: (2)隐式意图: Android(java)学习笔记218:开发一个多界面的应用程序之人 ...
 - Android(java)学习笔记162:开发一个多界面的应用程序之两种意图
		
1.两种意图: (1)显式意图: 在代码里面用intent设置要开启Activity的字节码.class文件: (2)隐式意图: Android(java)学习笔记218:开发一个多界面的应用程序之人 ...
 - Android自动化测试之Monkeyrunner学习笔记(一)
		
Android自动化测试之Monkeyrunner学习笔记(一) 因项目需要,开始研究Android自动化测试方法,对其中的一些工具.方法和框架做了一些简单的整理,其中包括Monkey.Monkeyr ...
 - Android(java)学习笔记267:Android线程池形态
		
1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
 - Android(java)学习笔记207:开源项目使用之gif view
		
1. 由于android没有自带的gif动画,我在Android(java)学习笔记198:Android下的帧动画(Drawable Animation) 播客中提到可以使用AnimationVie ...
 - Android(java)学习笔记71:生产者和消费者之等待唤醒机制
		
1. 首先我们根据梳理我们之前Android(java)学习笔记70中关于生产者和消费者程序思路: 2. 下面我们就要重点介绍这个等待唤醒机制: (1)第一步:还是先通过代码体现出等待唤醒机制 pac ...
 - Android(java)学习笔记167:Java中操作文件的类介绍(File + IO流)
		
1.File类:对硬盘上的文件和目录进行操作的类. File类是文件和目录路径名抽象表现形式 构造函数: 1) File(String pathname) Creat ...
 - Android(java)学习笔记160:Framework运行环境之 Android进程产生过程
		
1.前面Android(java)学习笔记159提到Dalvik虚拟机启动初始化过程,就下来就是启动zygote进程: zygote进程是所有APK应用进程的父进程:每当执行一个Android应用程序 ...
 - Android(java)学习笔记206:利用开源SmartImageView优化网易新闻RSS客户端
		
1.我们自己编写的SmartImageView会有很多漏洞,但是我们幸运的可以在网上利用开源项目的,开源项目中有很多成熟的代码,比如SmartImageView都编写的很成熟的 国内我们经常用到htt ...
 - Android(java)学习笔记205:网易新闻RSS客户端应用编写逻辑过程
		
1.我们的项目需求是编写一个新闻RSS浏览器,RSS(Really Simple Syndication)是一种描述和同步网站内容的格式,是使用最广泛的XML应用.RSS目前广泛用于网上新闻频道,bl ...
 
随机推荐
- nodejs+socket.io即时聊天实例
			
在这之前你应该先安装好 Node.js,安装过程不再讲解 首先在你的电脑上创建一个新目录,姑且命名为 chat,然后在该目录创建两个文件,分别是 app.js 和 index.html. app.js ...
 - CSS中常见的BUG调试
			
1.布局--layout 布局是windows提出的概念,用于控制元素的尺寸和定位. 拥有布局的元素负责自身及其子元素的尺寸及定位,而没有布局的元素仅仅能依靠近期的祖先元素进行控制. 通常在IE6中出 ...
 - VC 实现视图区背景颜色渐变填充
			
void CSTest1View::OnDraw(CDC* pDC) { CSTest1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: ...
 - 爱的歌我uhegierhiuerh5怕哦一
			
http://www.huihui.cn/share/8424421 http://www.huihui.cn/share/8424375 http://www.huihui.cn/share/842 ...
 - SDL Guide 中文译版
			
SDL即Simple DirectMedia Layer,类似DirectX,是完整的游戏.多媒体开发包,但不同的是它跨越几乎所有的平台,有各种语言的接口,多种语言的文档,而这一切都是广大志愿者完成的 ...
 - 深入理解 JBoss 7/WildFly Standalone 模式启动过程
			
概述 JBoss 7/WildFly Standalone 模式启动过程大致例如以下: 启动脚本 standalone.sh 启动 JBoss Modules,JBoss Modules 启动 JBo ...
 - VS2012配置astyle格式化代码
			
1.工具->扩展和更新,搜astyle插件,下载安装重启,当前是2.0版本. 2.工具->选项->AStyle Formatter->Edit,填入下面的,点击save,确定. ...
 - find . -iname "*.jpg"|xargs -i mv {} .;for i in `ls`; do mv -f $i `echo $i | sed 's/JPG/jpg/'`; done
			
find . -iname "*.jpg"|xargs -i mv {} .;for i in `ls`; do mv -f $i `echo $i | sed 's/JPG/jp ...
 - EasyUI初体验--右键弹框
			
在C/S中可能非常easy实现右键弹框,但在B/S中直到今天我才搞定,小小得瑟一下.只一个html页面,导入相关的Easy-UI类库就能搞定,Easy-UI类库下载地址 <!DOCTYPE ht ...
 - JavaFX游戏开发效率浅谈
			
声明: 本博客文章原创类别的均为个人原创,版权所有.转载请注明出处: http://blog.csdn.net/ml3947,另外本人的个人博客:http://www.wjfxgame.com. ...