好久没写博客了,前端时间一直在忙,也没去更新过。这次趁着有空,写下最近做项目的一些心得也好。
这次做项目在加载图片的时候,领导给出的要求是用univeser-imageloader来加载,之前也没用过这个,这次就权当是学习吧。
用法什么的我就不多说了。百度上一搜一大把。这次主要是讲一下在imageloader里面使用自定义缓存名称的一些心得。
首先先是imageloader的配置,因为imageloader是单例模式的,在一开始配置了在后面都不需要再进行配置。
package com.csdn.jt.game.activity;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import com.csdn.jiongtian.game.R;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.utils.StorageUtils;
import android.app.Application;
import android.graphics.Bitmap.Config;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
init();
}
private void init(){
File cacheFile = StorageUtils.getIndividualCacheDirectory(this, "cache");
File reserverFile = StorageUtils.getIndividualCacheDirectory(this, "reserverCache");
DisplayImageOptions option = new DisplayImageOptions.Builder().bitmapConfig(Config.RGB_565)//为了减少oom的可能性 建议还是加载图片质量为RGB_55会比较好
.cacheInMemory(true)//是否设置内存缓存
.cacheOnDisk(true)//是否设置磁盘缓存
.resetViewBeforeLoading(false)//加载图片之前是否复位,重置
.showImageForEmptyUri(R.drawable.ic_launcher) //加载的url为空时显示的图片(这里我是直接用的系统的图片)
.showImageOnFail(R.drawable.ic_launcher)//加载失败是显示的图片
.showImageOnLoading(R.drawable.ic_launcher)//加载过程中显示的图片
.delayBeforeLoading(200)//加载前等待时间
.build();
ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this)
.diskCacheFileNameGenerator(new Md5FileNameGenerator())//设置图片缓存名称(可以自定义图片的缓存名称,接下来就是说的这个)
.diskCacheFileCount(500)//设置图片缓存的文件数量
.threadPoolSize(3)//配置线程池的内线程的数量
.denyCacheImageMultipleSizesInMemory()
// 解码图像的大尺寸将在内存中缓存先前解码图像的小尺寸
.threadPriority(Thread.NORM_PRIORITY)//设置线程的优先级别
.memoryCache(new LruMemoryCache(16*1024*1024))//设置内存缓存的大小
.memoryCacheSize(16*1024*1024)//
.diskCacheSize(50 * 1024 * 1024) // 本地缓存大小50M
.diskCache(new UnlimitedDiskCache(cacheFile, reserverFile, new Md5FileNameGenerator()))//缓存路径,储存地址,缓存名称定义接口
.defaultDisplayImageOptions(option)
.tasksProcessingOrder(QueueProcessingType.LIFO) // 设置加载显示图片队列进程(这里设置为后进先出)
.build();
ImageLoader.getInstance().init(configuration);
}
}
接下来就是当时令我纠结很久的自定义图片缓存的问题了。用过的大部分都是知道,imageloader是会根据图片的尺寸大小进行图片缓存的,就像是当前100x200的imageview跟
170x200的imageview加载同一个url的时候,当100x200的图片加载完成之后,内存缓存里面关于当前url所对应的bitmap的键是为url_100x200,所以当170x200的图片加载同一个url的时候在内存缓存里面并不能拿到对应的bitmap,这个时候就会去加载磁盘缓存(如果你有设置磁盘缓存的话)。
做项目的时候为了安全性,我们都会在进行请求的时候带上当前安全票据,ticket。当时本人做项目的时候,领导要求图片加载的时候必须带上ticket才能去加载图片。也就是说加载一个用户A的头像,三次的url都会是不同的。这个时候就是出现一种第一次加载的时候,加载所有头像完毕后,退出后再进入,又要重新向服务器拿资源了。所以这个时候就要修改磁盘缓存的名称
/**
* 创建者:qjt
* 修改时间:2015-7-8 上午10:22:11
* 作用:自定义磁盘缓存名称设置
*/
public class SelfFileNameGenerator implements FileNameGenerator {
private static final String HASH_ALGORITHM = "MD5";
private static final int RADIX = 10 + 26;
@Override
public String generate(String imageUri) {//对传入的url进行统一的命名格式
if(isHeadImgUrl(imageUri)){
imageUri = getUrlKey(imageUri);
}
if(containTicket(imageUri)){
imageUri = removeTicket(imageUri);
}
byte[] md5 = getMD5(imageUri.getBytes());
BigInteger bi = new BigInteger(md5).abs();
return bi.toString(RADIX);
}
private byte[] getMD5(byte[] data) {
byte[] hash = null;
try {
MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
digest.update(data);
hash = digest.digest();
} catch (NoSuchAlgorithmException e) {
L.e(e);
}
return hash;
}
/**
* 因项目需要,对传入的url做判断
* @param key
* @return
*/
private boolean isHeadImgUrl(String key){
return key.contains("/base/head.do?");
}
/**
* 因为我只需要获取url中的userId所有在这里做了个筛选
* @param url
* @return
*/
private String getUrlKey(String url){
if(!url.endsWith("_")){
url += "_";
}
int startPoint = url.indexOf("?")+1;
int endPoint = url.lastIndexOf("&");
String key = url.substring(startPoint,endPoint+2);
return key;
}
private boolean containTicket(String url){
return url.contains("ticket=");
}
private String removeTicket(String url){
int startPosition = url.indexOf("ticket=");
String key = url.substring(0,startPosition);
return key;
}
}
这样我们就可以用自定义的格式替换原先系统默认的存储名称定义