详解Android 图片的三级缓存及图片压缩
为什么需要图片缓存
Android默认给每个应用只分配16M的内存,所以如果加载过多的图片,为了防止内存溢出,应该将图片缓存起来。图片的三级缓存分别是:
- 内存缓存
- 本地缓存
- 网络缓存
其中,内存缓存应优先加载,它速度最快;本地缓存次优先加载,它速度也快;网络缓存不应该优先加载,它走网络,速度慢且耗流量。
三级缓存的具体实现
网络缓存
- 根据图片的url去加载图片
- 在本地和内存中缓存
publicclassNetCacheUtils{
privateLocalCacheUtilsmLocalCacheUtils;
privateMemoryCacheUtilsmMemoryCacheUtils;
publicNetCacheUtils(LocalCacheUtilslocalCacheUtils,
MemoryCacheUtilsmemoryCacheUtils){
mLocalCacheUtils=localCacheUtils;
mMemoryCacheUtils=memoryCacheUtils;
}
/**
*从网络下载图片
*
*@paramivPic
*@paramurl
*/
publicvoidgetBitmapFromNet(ImageViewivPic,Stringurl){
newBitmapTask().execute(ivPic,url);//启动AsyncTask,
//参数会在doInbackground中获取
}
/**
*Handler和线程池的封装
*
*第一个泛型:参数类型第二个泛型:更新进度的泛型,第三个泛型是onPostExecute的返回结果
*
*
*/
classBitmapTaskextendsAsyncTask<Object,Void,Bitmap>{
privateImageViewivPic;
privateStringurl;
/**
*后台耗时方法在此执行,子线程
*/
@Override
protectedBitmapdoInBackground(Object...params){
ivPic=(ImageView)params[0];
url=(String)params[1];
ivPic.setTag(url);//将url和imageview绑定
returndownloadBitmap(url);
}
/**
*更新进度,主线程
*/
@Override
protectedvoidonProgressUpdate(Void...values){
super.onProgressUpdate(values);
}
/**
*耗时方法结束后,执行该方法,主线程
*/
@Override
protectedvoidonPostExecute(Bitmapresult){
if(result!=null){
StringbindUrl=(String)ivPic.getTag();
if(url.equals(bindUrl)){//确保图片设定给了正确的imageview
ivPic.setImageBitmap(result);
mLocalCacheUtils.setBitmapToLocal(url,result);//将图片保存在本地
mMemoryCacheUtils.setBitmapToMemory(url,result);//将图片保存在内存
System.out.println("从网络缓存读取图片啦...");
}
}
}
}
/**
*下载图片
*
*@paramurl
*@return
*/
privateBitmapdownloadBitmap(Stringurl){
HttpURLConnectionconn=null;
try{
conn=(HttpURLConnection)newURL(url).openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
conn.connect();
intresponseCode=conn.getResponseCode();
if(responseCode==200){
InputStreaminputStream=conn.getInputStream();
//图片压缩处理
BitmapFactory.Optionsoption=newBitmapFactory.Options();
option.inSampleSize=2;//宽高都压缩为原来的二分之一,此参数需要根据图片要展示的大小来确定
option.inPreferredConfig=Bitmap.Config.RGB_565;//设置图片格式
Bitmapbitmap=BitmapFactory.decodeStream(inputStream,null,option);
returnbitmap;
}
}catch(Exceptione){
e.printStackTrace();
}finally{
conn.disconnect();
}
returnnull;
}
}
本地缓存
两个方法:设置本地缓存,获取本地缓存
publicclassLocalCacheUtils{
publicstaticfinalStringCACHE_PATH=Environment
.getExternalStorageDirectory().getAbsolutePath()+"/local_cache";
/**
*从本地sdcard读图片
*/
publicBitmapgetBitmapFromLocal(Stringurl){
try{
StringfileName=MD5Encoder.encode(url);
Filefile=newFile(CACHE_PATH,fileName);
if(file.exists()){
Bitmapbitmap=BitmapFactory.decodeStream(newFileInputStream(
file));
returnbitmap;
}
}catch(Exceptione){
e.printStackTrace();
}
returnnull;
}
/**
*向sdcard写图片
*
*@paramurl
*@parambitmap
*/
publicvoidsetBitmapToLocal(Stringurl,Bitmapbitmap){
try{
StringfileName=MD5Encoder.encode(url);
Filefile=newFile(CACHE_PATH,fileName);
FileparentFile=file.getParentFile();
if(!parentFile.exists()){//如果文件夹不存在,创建文件夹
parentFile.mkdirs();
}
//将图片保存在本地
bitmap.compress(CompressFormat.JPEG,100,
newFileOutputStream(file));
}catch(Exceptione){
e.printStackTrace();
}
}
}
内存缓存
两个方法:设置内存缓存,获取内存缓存
问题:
如果使用HashMap存储图片时,当图片越来越多时,会导致内存溢出,因为它是强引用,java的垃圾回收器不会回收。
如若改成软引用SoftReference(内存不够时,垃圾回收器会考虑回收),仍有一个问题:在android2.3+,系统会优先将SoftReference的对象提前回收掉,即使内存够用。
解决办法:可以用LruCache来解决上述内存不回收或提前回收的问题。leastrecentllyuse最少最近使用算法它会将内存控制在一定的大小内,超出最大值时会自动回收,这个最大值开发者自己定
publicclassMemoryCacheUtils{
//privateHashMap<String,SoftReference<Bitmap>>mMemoryCache=new
//HashMap<String,SoftReference<Bitmap>>();
privateLruCache<String,Bitmap>mMemoryCache;
publicMemoryCacheUtils(){
longmaxMemory=Runtime.getRuntime().maxMemory()/8;//模拟器默认是16M
mMemoryCache=newLruCache<String,Bitmap>((int)maxMemory){
@Override
protectedintsizeOf(Stringkey,Bitmapvalue){
intbyteCount=value.getRowBytes()*value.getHeight();//获取图片占用内存大小
returnbyteCount;
}
};
}
/**
*从内存读
*
*@paramurl
*/
publicBitmapgetBitmapFromMemory(Stringurl){
//SoftReference<Bitmap>softReference=mMemoryCache.get(url);
//if(softReference!=null){
//Bitmapbitmap=softReference.get();
//returnbitmap;
//}
returnmMemoryCache.get(url);
}
/**
*写内存
*
*@paramurl
*@parambitmap
*/
publicvoidsetBitmapToMemory(Stringurl,Bitmapbitmap){
//SoftReference<Bitmap>softReference=new
//SoftReference<Bitmap>(bitmap);
//mMemoryCache.put(url,softReference);
mMemoryCache.put(url,bitmap);
}
}
图片压缩
//图片压缩处理(在从网络获取图片的时候就进行压缩) BitmapFactory.Optionsoption=newBitmapFactory.Options(); option.inSampleSize=2;//宽高都压缩为原来的二分之一,此参数需要根据图片要展示的大小来确定 option.inPreferredConfig=Bitmap.Config.RGB_565;//设置图片格式 Bitmapbitmap=BitmapFactory.decodeStream(inputStream,null,option);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。