详解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);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。