ImageLoader管理本地图片
前面我们讨论了ImageLoader在图片下载与缓存中的一些使用方法,那么为什么我们要用ImageLoader管理本地图片呢?
考虑以下一些情况
在App中,我们常常会进行位图的处理,如果我们需要将图片生成的位图保存,是否能结合到我们的图片框架中?最近项目需要将一张位图做模糊处理,这样的逐点操作非常消耗内存和时间,如果我们直接将处理好的位图压缩并存储在本地,下次打开时就不需要再次处理。
我们经常需要下载很多图片,假如我们要做一个网络相册,用户想修改相册中的一些图片,修改完后要上传。但是我们知道,ImageLoader的硬盘缓存命名并非标准的图片格式,我们无法预览和上传。所以我们必须知道这些图片的存储位置,然后将其拷贝出来,将文件名改成我们服务器规定的命名格式,然后再上传。
综上,我们统一管理图片的各种路径和命名,这样ImageLoder不仅是一个图片加载框架,而完全变成了App的图片管理框架。根据目前的需要,添加了两个功能,日后再不断完善。
结合昨天写的拍照裁剪相关的博文,我们在此打造一个功能比较全面的图片管理demo。
包含功能
1.ImageLoader框架的所有功能
2.图片的拍照、选取及裁剪
3.对拍照图片进行处理的,并将处理结果保存到本地,同时使用ImageLoader加载这种图片
4.根据Uri将网络图片的硬盘缓存文件获取到并拷贝到我们的指定路径下,指定文件命名
其中前两条可以参考以前的博文,今天主要实现了后面两条功能。
代码链接: http://download.csdn.net/detail/lidec/9360771
项目链接: https://git.oschina.net/vonchenchen/ImageLoaderCacheDemo.git
主要流程
文件结构管理
/**
* Created by vonchenchen on 2015/12/11 0011.
*/
public class ImageLoaderManager {
//ImageView 的文件缓存
public final static String FILE_IMAGELOADER_CACHE = Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/vonchenchen/ImageLoaderCache/";
//保存裁剪后照片的路径
public final static String FILE_SAVEPATH = Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/vonchenchen/Portrait/";
//保存直接拍照后未经剪裁照片的路径
public final static String FILE_SAVEPATH_CAMERA = Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/vonchenchen/Camera/";
//保存经过模糊处理后的图片路径
public final static String FILE_SAVEPATH_FUZZY = Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/vonchenchen/Fuzzy/";
//使用ImageLoader下载后需要上传的图片,单独拷贝到这个目录下,并将文件名修改为相应的格式
public final static String FILE_SAVEPATH_UPLOAD = Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/vonchenchen/Upload/";
//裁剪后照片的前缀名 文件名:FILE_SAVENAME + timeStamp + ".jpg"
public final static String FILE_SAVENAME_CROP = "vonchenchen";
//直接拍照后照片的前缀名 文件名:FILE_SAVENAME_CAMERA + timeStamp + ".jpg"/other
public final static String FILE_SAVENAME_CAMERA = "vonchenchen";
}
管理生成的位图
分析见注释
//解压图片
protraitBitmap = ImageUtils.convertToBitmap(protraitPath, 200, 200);
//将位图进行处理
protraitBitmap = BlurUtil.blurBitmap(protraitBitmap, MainActivity.this);
//将处理结果压缩为jpeg,写入指定文件
protraitUri = saveCroppedImage(protraitBitmap, "test");
//用ImageLoader加载这个文件 此处没有知道option,默认不使用内存缓存,可以根据实际情况进行调整
ImageLoader.getInstance().displayImage(protraitUri.toString(), mImageView, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String s, View view) {
}
@Override
public void onLoadingFailed(String s, View view, FailReason failReason) {
}
@Override
public void onLoadingComplete(String s, View view, Bitmap bitmap) {
//clearDocument(FILE_SAVEPATH_FUZZY);
}
@Override
public void onLoadingCancelled(String s, View view) {
}
});
}
管理下载缓存
ImageLoader下载后的图片命名是使用FileNameGenerator接口来设置,默认是Uri的HashCode。所以我们可以打开ImageLoader的缓存文件夹进行查看,里面的文件都是数字,但是由于没有后缀名,所以手机并不能识别。我们可以尝试给这些文件加个后缀,比如如果下载的是jpeg图,那么就加个.jpg,我们就会发现图片可以正常显示。找到这个图片,了解了其命名是用Uri的hashCode时,就可以获取图片的路径,此时我们即可将图片拷贝到另一个用于管理图片的文件中,并且修改其命名。由于ImageLoader中的硬盘缓存可能被回收,所以如果我们可能需要这张图,就在其下载完毕后立即拷贝。
//获取图片在硬盘缓存上的路径
String path = getImageLoaderDiskCacheImageName(uriStr, new HashCodeFileNameGenerator());
System.out.print(path);
//将图片从ImageView维护的硬盘缓存中取出,拷贝到我们指定的路径下
File file = copyToUpLoadFileAndRename(path, "upload.jpg");
//获取当前图片,这种常用于下载后上传,需要知道图片路径
String uploadPath = file.getAbsolutePath();
获取文件名
/**
* 获取ImageLoader的硬盘缓存中对应的路径
* @param uriStr 图片资源uri
* @param generator 给图片设置名字的generator,需要和config的config中设置的generator一样
* @return
*/
private String getImageLoaderDiskCacheImageName(String uriStr, FileNameGenerator generator){
String name = generator.generate(uriStr);
String path = ImageLoaderManager.FILE_IMAGELOADER_CACHE + name;
return path;
}
拷贝文件
/**
* 将图片从ImageLoader的硬盘缓存路径拷贝到上传路径,并指定新的文件名
* 复制成功返回复制的文件
* @param path 源路径
* @param newName 我们指定的文件名
*/
public File copyToUpLoadFileAndRename(String path, String newName){
File src = new File(path);
File des = new File(ImageLoaderManager.FILE_SAVEPATH_UPLOAD + newName);
String savePath = "";
String storageState = Environment.getExternalStorageState();
if (storageState.equals(Environment.MEDIA_MOUNTED)) {
savePath = ImageLoaderManager.FILE_SAVEPATH_UPLOAD;
File savedir = new File(savePath);
if (!savedir.exists()) {
savedir.mkdirs();
}
}
if(copyToAnotherDocument(src, des) != -1){
return des;
}else{
return null;
}
}
/**
* 将一个文件拷贝到指定文件目录下,并修文件名
* @param src
* @param des
*/
private int copyToAnotherDocument(File src, File des){
//long time=new Date().getTime();
int length=1024*10;
try {
FileInputStream in=new FileInputStream(src);
FileOutputStream out=new FileOutputStream(des);
byte[] buffer=new byte[length];
while(true){
int ins=in.read(buffer);
if(ins==-1){
in.close();
out.flush();
out.close();
//return new Date().getTime()-time;
return 1;
}else
out.write(buffer,0,ins);
}
}catch (Exception e){
}finally {
}
return -1;
}
这样,无论是网络加载的图片还是我们自己生成的图片,都被我们抓住了。需要注意的是,使用下载时,我们可以灵活使用option配置ImageLoader的任务,根据不同的情景使确定是否使用内存缓存以及硬盘缓存。