Android图片加载的缓存类
本文为大家分享了Android图片加载的缓存类,供大家参考,具体内容如下
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.lang.ref.SoftReference;
importjava.net.HttpURLConnection;
importjava.net.URL;
importjava.util.LinkedHashMap;
importjava.util.concurrent.ConcurrentHashMap;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importandroid.graphics.Bitmap;
importandroid.graphics.BitmapFactory;
importandroid.os.Build;
importandroid.os.Handler;
importandroid.text.TextUtils;
/**
*图片加载器,主要功能是从网络中下载图片并缓存。这里之所以另写一个功能类似重复的原因是之前旧的图片加载逻辑感觉非常复杂,我这里写个轻量级的
*
*@authorH3c
*
*/
publicclassImageLoaderEngine{
publicstaticfinalintLOAD_IMG_SUCCESS=2010;
privatefinalintMAX_CAPACITY=Build.VERSION.SDK_INT>Build.VERSION_CODES.GINGERBREAD_MR1?50:10;//一级缓存缓存图片数
privatestaticImageLoaderEngineinstance;
privatestaticHandlermHandler;
privateExecutorServicepool;//后台线程池
//这里用LinkedHashMap不用LruCache的原因是LruCache直接申请内存大小而不是图片个数。此App已经有一个全局的LruCache了,重复申请内存大小对应用不利
privateLinkedHashMap<String,Bitmap>mFirstLevelCache;//<momentId>一级缓存,硬链接bitmap,只保留最近用的图片。
privateConcurrentHashMap<String,SoftReference<Bitmap>>mSecondLevelCache;//<momentId>
publicstaticImageLoaderEnginegetInstance(Handlerhandler){
if(instance==null){
instance=newImageLoaderEngine();
}
if(handler!=null){
mHandler=handler;
}
returninstance;
}
privateImageLoaderEngine(){
pool=Executors.newFixedThreadPool(4);//默认线程池大小为6
initCache();
}
privatevoidinitCache(){
mFirstLevelCache=newLinkedHashMap<String,Bitmap>(MAX_CAPACITY/2,
0.75f,true){
privatestaticfinallongserialVersionUID=1L;
protectedbooleanremoveEldestEntry(Entry<String,Bitmap>eldest){
if(size()>MAX_CAPACITY){//超过一级缓存大小后会挪到二级缓存中
mSecondLevelCache.put(eldest.getKey(),
newSoftReference<Bitmap>(eldest.getValue()));
returntrue;
}
returnfalse;
};
};
mSecondLevelCache=newConcurrentHashMap<String,SoftReference<Bitmap>>();//<momentId>
}
/**
*移除缓存
*@paramkey
*/
publicvoiddeleteCacheByKey(Stringkey){
StringsdCacheingPath=IOHelper.getCachedPicturePath(
Global.packageName,key);
StringsdCacheedPath=sdCacheingPath+".png";
Filefile=newFile(sdCacheingPath);
if(file.exists()){
file.delete();
}
file=newFile(sdCacheedPath);
if(file.exists()){
file.delete();
}
mFirstLevelCache.remove(key);
mSecondLevelCache.remove(key);
}
/**
*释放资源
*/
publicvoidrecycleImageLoader(){
newThread(newRunnable(){
@Override
publicvoidrun(){
if(pool!=null){
pool.shutdownNow();
}
if(mFirstLevelCache!=null){
for(Bitmapbmp:mFirstLevelCache.values()){
if(bmp!=null){
bmp.recycle();
bmp=null;
}
}
mFirstLevelCache.clear();
mFirstLevelCache=null;
}
if(mSecondLevelCache!=null){
mSecondLevelCache.clear();
}
mHandler=null;
}
}).start();
}
/**
*后台请求图片
*
*@paramitem
*/
publicvoidloadImageByMoment(finalNMomentmoment,StringphotoTag){
if(moment.isPicture()
||moment.isVideo()){
Stringid=moment.id+photoTag;
loadImageByUrl(id+"",moment.getPicture(Global.widthPixels/3*2),moment.orientation);
}
}
/**
*后台请求图片
*@paramkey
*@paramurl
*/
publicvoidloadImageByUrl(finalStringkey,finalStringurl,finalintorientation){
pool.submit(newRunnable(){
publicvoidrun(){
LogHelper.e("ImageLoaderEngine","从网络中下载");
//如果内存中有就算了
if(mFirstLevelCache.get(key)!=null
||mSecondLevelCache.get(key)!=null){//如果图片已经缓存了
LogHelper.e("ImageLoaderEngine","下载图片错误1");
return;
}
//如果SD卡缓存中有就算了
finalStringsdCacheingPath=IOHelper.getCachedPicturePath(
Global.packageName,key);
FilecacheingFile=newFile(sdCacheingPath);
if(cacheingFile.exists()){//如果正在缓存就算了
longcurrentTime=System.currentTimeMillis();
if((currentTime-cacheingFile.lastModified())>2*60*1000){
LogHelper.e("ImageLoaderEngine","2分钟都还没下载完,准备删除它.."+currentTime+"="+cacheingFile.lastModified());
cacheingFile.delete();
}else{
getBitmapFromNetworkAndAddToMemory(url,key,orientation);
LogHelper.e("ImageLoaderEngine","第二次进来应该走这里..");
return;
}
}
StringsdCacheedPath=sdCacheingPath+".png";//缓存完成后会改名字,否则会导致缓存错误,图片变黑
FilecacheedFile=newFile(sdCacheedPath);
if(cacheedFile.exists()){//如果缓存了就算了
LogHelper.e("ImageLoaderEngine","下载图片错误2");
return;
}
getBitmapFromNetworkAndAddToMemory(url,key,orientation);
}
});
}
privatevoidgetBitmapFromNetworkAndAddToMemory(Stringurl,Stringkey,intorientation){
Bitmapbmp=getBitmapFromUrl(url);
if(bmp!=null){
LogHelper.e("ImageLoaderEngine","下载网络图片成功");
if(key.endsWith("_DetailDaily")){
bmp=scaledBitmap(bmp,Global.getThumbWidth());
}
if(orientation!=0){
mFirstLevelCache.put(key,ViewHelper.rotateBitmap(orientation,bmp));//从网络下载后直接显示
}else{
mFirstLevelCache.put(key,bmp);//从网络下载后直接显示
}
if(mHandler!=null){
mHandler.removeMessages(LOAD_IMG_SUCCESS);
mHandler.sendEmptyMessageDelayed(
LOAD_IMG_SUCCESS,600);//延时提示没有数据了
}
finalStringsdCacheingPath=IOHelper.getCachedPicturePath(
Global.packageName,key);
saveBitmapToFile(sdCacheingPath,bmp);
}else{
LogHelper.e("ImageLoaderEngine","下载网络图片失败...");
}
}
/**
*直接从网络中获取
*@paramurl
*@return
*/
publicBitmapgetBitmapFromUrl(Stringurl){
URLmyFileUrl=null;
Bitmapbitmap=null;
InputStreamis=null;
try{
if(!UIUtils.isNetworkAvailable(MyApplication.getInstance())){
returnnull;
}
myFileUrl=newURL(url);
HttpURLConnectionconn=(HttpURLConnection)myFileUrl
.openConnection();
conn.setDoInput(true);
conn.connect();
is=conn.getInputStream();
bitmap=BitmapFactory.decodeStream(is);
}catch(Exceptione){
try{
if(is!=null){
is.close();
}
}catch(IOExceptione1){
e1.printStackTrace();
}
e.printStackTrace();
}
returnbitmap;
}
publicBitmapgetImageInMemory(NMomentmoment){
returngetImageInMemory(moment,"");
}
/**
*新增接口,可以根据tag重新标识Moment,这样可以扩展应用场景,比如首页需要大图,进入相集页需要小图
*@parammoment
*@paramphotoTag
*@return
*/
publicBitmapgetImageInMemory(NMomentmoment,StringphotoTag){
Stringid=moment.id+photoTag;
Bitmapbmp=null;
//1.从一级缓存中获取
bmp=getFromFirstLevelCache(id);
if(bmp!=null&&!bmp.isRecycled()){
LogHelper.e("ImageLoaderEngine","一级缓存获取:"+id);
returnbmp;
}
//2.从二级缓存中获取
bmp=getFromSecondLevelCache(id);
if(bmp!=null&&!bmp.isRecycled()){
LogHelper.e("ImageLoaderEngine","二级缓存获取:"+id);
returnbmp;
}
if(bmp!=null&&bmp.isRecycled()){
returnnull;
}else{
returnbmp;
}
}
publicvoidsetImage(Stringkey,Bitmappicture){
mFirstLevelCache.put(key,picture);
}
/**
*获取图片
*/
publicBitmapgetImage(NMomentmoment){
returngetImage(moment,"");
}
publicBitmapgetImage(NMomentmoment,StringphotoTag){
Stringid=moment.id+photoTag;
Bitmapbmp=null;
//1.从一级缓存中获取
bmp=getFromFirstLevelCache(id);
if(bmp!=null&&!bmp.isRecycled()){
LogHelper.e("ImageLoaderEngine","一级缓存获取:"+id);
returnbmp;
}
//2.从二级缓存中获取
bmp=getFromSecondLevelCache(id);
if(bmp!=null&&!bmp.isRecycled()){
LogHelper.e("ImageLoaderEngine","二级缓存获取:"+id);
returnbmp;
}
//3.从SD卡缓存中获取
bmp=getFromSDCache(moment,photoTag);
if(bmp!=null&&!bmp.isRecycled()){
LogHelper.e("ImageLoaderEngine","SD卡缓存获取:"+id);
returnbmp;
}
//4.从网络中获取
loadImageByMoment(moment,photoTag);
//LogHelper.e("ImageLoaderEngine","本地获取图片失败:"+moment.id+"="+moment.getPicture());
if(bmp!=null&&bmp.isRecycled()){
returnnull;
}else{
returnbmp;
}
}
publicBitmapgetImage(Stringkey,Stringurl){
Bitmapbmp=null;
//1.从一级缓存中获取
bmp=getFromFirstLevelCache(key);
if(bmp!=null&&!bmp.isRecycled()){
returnbmp;
}
//2.从二级缓存中获取
bmp=getFromSecondLevelCache(key);
if(bmp!=null&&!bmp.isRecycled()){
returnbmp;
}
//3.从SD卡缓存中获取
bmp=getFromSDCacheByKey(key,0);
if(bmp!=null&&!bmp.isRecycled()){
returnbmp;
}
//4.从网络中获取
loadImageByUrl(key,url,0);
if(bmp!=null&&bmp.isRecycled()){
returnnull;
}else{
returnbmp;
}
}
/**
*一级缓存获取图片
*
*@paramimgId
*@return
*/
privateBitmapgetFromFirstLevelCache(StringimgId){
Bitmapbitmap=null;
synchronized(mFirstLevelCache){
bitmap=mFirstLevelCache.get(imgId);
if(bitmap!=null){
mFirstLevelCache.remove(imgId);
mFirstLevelCache.put(imgId,bitmap);
}
}
returnbitmap;
}
/**
*二级缓存获取图片
*
*@paramurl
*@return
*/
privateBitmapgetFromSecondLevelCache(StringimgId){
Bitmapbitmap=null;
SoftReference<Bitmap>softReference=mSecondLevelCache.get(imgId);
if(softReference!=null){
bitmap=softReference.get();
if(bitmap==null){
mSecondLevelCache.remove(imgId);
}
}
returnbitmap;
}
/**
*从SD卡缓存获取图片,并放入一级缓存中
*
*@parammoment
*@return
*@throwsIOException
*/
privateBitmapgetFromSDCache(finalNMomentmoment,finalStringphotoTag){
Bitmapdrawable=null;
Stringid=moment.id+photoTag;
StringsdCacheingPath=IOHelper.getCachedPicturePath(Global.packageName,
id);
StringsdCacheedPath=sdCacheingPath+".png";
if(moment.isLocal){
if(moment.isVideo()){
//获取本地路径
sdCacheedPath=moment.getPicture(Global.widthPixels/3*2);
}else{
sdCacheedPath=moment.local_res_path;
}
}
FilecacheFile=newFile(sdCacheedPath);
if(!cacheFile.exists()){//如果没有缓存完成就退出
LogHelper.e("ImageLoaderEngine","找不到缓存文件:"+sdCacheedPath);
if(!TextUtils.isEmpty(moment.local_res_path)){//如果本地有图片,就先用本地图片代替
sdCacheedPath=moment.local_res_path;
cacheFile=newFile(sdCacheedPath);
if(cacheFile.exists()&&!GlobalData.PHONE_MANUFACTURER.equalsIgnoreCase("samsung")){
LogHelper.e("ImageLoaderEngine","AK47...:"+GlobalData.PHONE_MANUFACTURER);//先从本地找替代图片..
newThread(newRunnable(){//从网络下载
@Override
publicvoidrun(){
loadImageByMoment(moment,photoTag);
}
}).start();
returngetFitPhoto(sdCacheedPath,moment,cacheFile);
}else{
returnnull;
}
}else{
returnnull;
}
}
drawable=getFitPhoto(sdCacheedPath,moment,cacheFile);
if(drawable!=null){
if(moment.orientation!=0){
drawable=ViewHelper
.rotateBitmap(moment.orientation,drawable);
}
if(mFirstLevelCache!=null){
mFirstLevelCache.put(id,drawable);
}
}else{
cacheFile.delete();
}
returndrawable;
}
privateBitmapgetFitPhoto(StringsdCacheedPath,NMomentmoment,FilecacheFile){
FileInputStreamfs=null;
Bitmapresult;
try{
BitmapFactory.Optionsoptions=newBitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeFile(sdCacheedPath,options);
inthRatio=(int)Math.ceil(options.outHeight
/(float)moment.picture_height);//算高度
intwRatio=(int)Math.ceil(options.outWidth
/(float)Global.widthPixels);//算宽度
if(hRatio>1||wRatio>1){
if(hRatio>wRatio){
options.inSampleSize=hRatio;
}else
options.inSampleSize=wRatio;
}
options.inPurgeable=true;
options.inInputShareable=true;
options.inDither=false;
options.inJustDecodeBounds=false;
try{
fs=newFileInputStream(cacheFile);
}catch(FileNotFoundExceptione){
e.printStackTrace();
}
result=BitmapFactory.decodeFileDescriptor(fs.getFD(),null,
options);
}catch(Exceptione){
thrownewRuntimeException(e);
}finally{
if(fs!=null){
try{
fs.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
returnresult;
}
privateBitmapgetFromSDCacheByKey(Stringkey,intorientation){
Bitmapdrawable=null;
FileInputStreamfs=null;
StringsdCacheedPath=IOHelper.getCachedPicturePath(
Global.packageName,key)+".png";
FilecacheFile=newFile(sdCacheedPath);
if(!cacheFile.exists()){//如果没有缓存完成就退出
returnnull;
}
try{
BitmapFactory.Optionsoptions=newBitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeFile(sdCacheedPath,options);
intwRatio=(int)Math.ceil(options.outWidth
/(float)Global.widthPixels);//算宽度
options.inSampleSize=wRatio;
options.inPurgeable=true;
options.inInputShareable=true;
options.inDither=false;
options.inJustDecodeBounds=false;
try{
fs=newFileInputStream(cacheFile);
}catch(FileNotFoundExceptione){
e.printStackTrace();
}
drawable=BitmapFactory.decodeFileDescriptor(fs.getFD(),null,
options);
if(drawable!=null){
if(orientation!=0){
drawable=ViewHelper.rotateBitmap(orientation,drawable);
}
mFirstLevelCache.put(key,drawable);
}else{
cacheFile.delete();
}
}catch(Exceptione){
thrownewRuntimeException(e);
}finally{
if(fs!=null){
try{
fs.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
returndrawable;
}
/**
*创建一个灰色的默认图
*@parammoment
*@return
*/
publicBitmapgetDefaultBitmap(NMomentmoment){
returnImageHelper.createBitmap(moment.picture_width,moment.picture_height,
R.color.image_bg_daily);
}
/**
*保存Bitmap文件到sd卡,传入jpg结尾的路径
*@paramfilePath
*@parammBitmap
*/
publicvoidsaveBitmapToFile(StringfilePath,BitmapmBitmap){
try{
Filefile=newFile(filePath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(file.exists()&&file.length()>0){
longcurrentTime=System.currentTimeMillis();
if((currentTime-file.lastModified())>2*60*1000){
LogHelper.e("ImageLoaderEngine",
"2分钟都还没下载完,准备删除它.."+currentTime+"="
+file.lastModified());
file.delete();
}else{
return;
}
}else{
file.createNewFile();
}
FileOutputStreamfOut=null;
fOut=newFileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.JPEG,80,fOut);
fOut.flush();
fOut.close();
file.renameTo(newFile(filePath+".png"));
}catch(Exceptione){
e.printStackTrace();
LogHelper.e("ImageLoaderEngine","保存图片错误:"+e);
}
LogHelper.e("ImageLoaderEngine","保存网络图片成功"+filePath+".png");
}
/**
*保存文件至缓存,这里重写而不用IOHelper里面的原因是IOHelper里面过于复杂
*
*@paramurl
*@paramfilePath
*@return
*/
publicbooleansaveUrlBitmapToFile(Stringurl,StringfilePath){
if(TextUtils.isEmpty(filePath)){
returnfalse;
}
FileiconFile=newFile(filePath);
if(iconFile.getParentFile()==null){
returnfalse;
}
if(!iconFile.getParentFile().exists()){
iconFile.getParentFile().mkdirs();
}
if(iconFile.exists()&&iconFile.length()>0){
longcurrentTime=System.currentTimeMillis();
if((currentTime-iconFile.lastModified())>2*60*1000){
LogHelper.e("ImageLoaderEngine","2分钟都还没下载完,准备删除它.."+currentTime+"="+iconFile.lastModified());
iconFile.delete();
}else{
returntrue;
}
}
FileOutputStreamfos=null;
InputStreamis=null;
try{
fos=newFileOutputStream(filePath);
is=newURL(url).openStream();
intdata=is.read();
while(data!=-1){
fos.write(data);
data=is.read();
}
}catch(IOExceptione){
LogHelper.e("ImageLoaderEngine","ImageLoaderEngine下载图片错误"+e);
iconFile.delete();
e.printStackTrace();
returnfalse;
}finally{
try{
if(is!=null){
is.close();
}
if(fos!=null){
fos.close();
}
}catch(IOExceptione){
e.printStackTrace();
}
}
iconFile.renameTo(newFile(filePath+".png"));
returntrue;
}
/**
*缩放bitmap
*@parambmp
*@paramscaledValue缩放值
*@return
*/
publicBitmapscaledBitmap(Bitmapbmp,intscaledValue){
intbmpWidth=bmp.getWidth();
intbmpHeight=bmp.getHeight();
if(bmpWidth>=bmpHeight){//横图
bmpWidth=(bmpWidth*scaledValue/bmpHeight);
bmpHeight=scaledValue;
}else{
bmpHeight=(bmpHeight*scaledValue/bmpWidth);
bmpWidth=scaledValue;
}
BitmapscaledBmp=Bitmap.createScaledBitmap(bmp,bmpWidth,bmpHeight,true);
bmp.recycle();
bmp=null;
returnscaledBmp;
}
}
以上就是一个完整的Android图片加载缓存类,希望对大家的学习有所帮助。