Android 开发中对图片的加载恨常见,为了防止出现内存溢出,采用三级缓存:
内存缓存,
本地缓存(sd),
网络缓存。
从网络下载的图片保存到内存和sd卡中,之后调用可以直接从内存或者sd卡读出
/** * 内存缓存 * @author xiongt * */ public class MemoryCacheUtils { private LruCache<String, Bitmap> mMemoryCache; public MemoryCacheUtils() { long maxMemory = Runtime.getRuntime().maxMemory(); // 8;// 模拟器默认是16M mMemoryCache = new LruCache<String, Bitmap>((int)(maxMemory)){ @Override protected int sizeOf(String key, Bitmap value) { int byteCount = value.getRowBytes()*value.getHeight();//获取图片占用内存大小 return byteCount; } }; } /** * 从内存读 * @param url * @return */ public Bitmap getBitmapFromMemory(String url){ return mMemoryCache.get(url); } /** * 写内存 */ public void setBitmapToMemory(String url,Bitmap bitmap){ mMemoryCache.put(url, bitmap); } } /** * 本地缓存(sd卡) * @author xiongt * */ public class LocalCacheUtils { public static final String CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/kdumpda_data"; /** * 向SD卡写图片 * @param url * @param bitmap */ public void setBitmapToLocal(String url,Bitmap bitmap){ try { // String fileName = MD5Encoder.encode(url); String fileName = url; File file = new File(CACHE_PATH, fileName); File fileParent = file.getParentFile(); if(!fileParent.exists()){// 如果文件夹不存在, 创建文件夹 fileParent.mkdirs(); } //将图片保存到本地 bitmap.compress(CompressFormat.JPEG, 100,new FileOutputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); } } /** * 从SD卡读图片 */ public Bitmap getBitmapFromLocal(String url){ try { String fileName = url; File file = new File(CACHE_PATH, fileName); if(file.exists()){ Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file)); return bitmap; } } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } } /** * 网络缓存 * @author xiongt * */ public class NetCacheUtils { private LocalCacheUtils mLocalCacheUtils; private MemoryCacheUtils mMemoryCacheUtils; public NetCacheUtils(LocalCacheUtils mLocalCacheUtils, MemoryCacheUtils mMemoryCacheUtils) { this.mLocalCacheUtils = mLocalCacheUtils; this.mMemoryCacheUtils = mMemoryCacheUtils; } //根据图片的url去加载图片 //在本地和内存中缓存 /** * 从网络下载图片(异步) * @param ivPic * @param url * @return */ public void getBitmapFromNet(ImageView ivPic,String url){ new BitmapTask().execute(ivPic,url);//启动AsyncTask,参数在doInBackground中获取 } /** * 异步任务是 Handler 和线程池的封装 * 泛型,第一个是参数,第二个是进度更新,第三个是返回结果 * @author xiongt * */ class BitmapTask extends AsyncTask<Object, Void, Bitmap>{ private ImageView ivPic; private String url; /** * 更新进度,主线程 */ @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values);//在doInBackground中调用publishProgress()方法更新 } /** * 后台耗时方法在此进行,子线程 */ @Override protected Bitmap doInBackground(Object... params) { ivPic = (ImageView) params[0]; url = (String) params[1]; ivPic.setTag(url);// 将url和imageview绑定 return downloadBitmap(url); } /** * 耗时操作完成后,执行该方法,主线程 */ @Override protected void onPostExecute(Bitmap result) { if(result != null){ String bindUrl = (String) ivPic.getTag(); if(url.equals(bindUrl)){// 确保图片设定给了正确的imageview ivPic.setImageBitmap(result); mLocalCacheUtils.setBitmapToLocal(url, result);// 将图片保存在本地 mMemoryCacheUtils.setBitmapToMemory(url, result);// 将图片保存在内存 } } super.onPostExecute(result); } } /** * 下载图片 * @param url * @return */ public Bitmap downloadBitmap(String url) { HttpURLConnection conn = null; try { conn = (HttpURLConnection) new URL(url).openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); conn.setRequestMethod("GET"); conn.connect(); int responseCode = conn.getResponseCode(); if(responseCode == 200){ InputStream inputStream = conn.getInputStream(); //图片压缩处理 BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定 options.inPreferredConfig = Bitmap.Config.ARGB_8888;//设置图片格式 Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options); return bitmap; } } catch (Exception e) { e.printStackTrace(); } finally{ conn.disconnect(); } return null; } }