- //内存缓存
- public class ImageMemoryCache {
- /**
- * 从内存读取数据速度是最快的,为了更大限度使用内存,这里使用了两层缓存。 硬引用缓存不会轻易被回收,用来保存常用数据,不常用的转入软引用缓存。
- */
- privatestatic finalint SOFT_CACHE_SIZE = 15;// 软引用缓存容量
- privatestatic LruCache<String, Bitmap> mLruCache; // 硬引用缓存
- privatestatic LinkedHashMap<String, SoftReference<Bitmap>>mSoftCache; // 软引用缓存
- public ImageMemoryCache(Context context) {
- int memClass = ((ActivityManager) context
- .getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
- int cacheSize = 1024 * 1024 * memClass / 4;// 硬引用缓存容量,为系统可用内存的1/4
- mLruCache =new LruCache<String, Bitmap>(cacheSize) {
- @Override
- protectedint sizeOf(String key, Bitmap value) {
- if (value !=null)
- return value.getRowBytes() * value.getHeight();
- else
- return 0;
- }
- @Override
- protectedvoid entryRemoved(boolean evicted, String key,
- Bitmap oldValue, Bitmap newValue) {
- if (oldValue !=null)
- // 硬引用缓存容量满的时候,会根据LRU算法把最近没有被使用的图片转入此软引用缓存
- mSoftCache.put(key,new SoftReference<Bitmap>(oldValue));
- }
- };
- mSoftCache =new LinkedHashMap<String, SoftReference<Bitmap>>(
- SOFT_CACHE_SIZE, 0.75f,true) {
- privatestatic final long serialVersionUID = 6040103833179403725L;
- @Override
- protectedboolean removeEldestEntry(
- Entry<String, SoftReference<Bitmap>> eldest) {
- if (size() >SOFT_CACHE_SIZE) {
- returntrue;
- }
- returnfalse;
- }
- };
- }
- /**
- * 从缓存中获取图片
- */
- public Bitmap getBitmapFromCache(String url) {
- Bitmap bitmap;
- // 先从硬引用缓存中获取
- synchronized (mLruCache) {
- bitmap = mLruCache.get(url);
- if (bitmap !=null) {
- // 如果找到的话,把元素移到LinkedHashMap的最前面,从而保证在LRU算法中是最后被删除
- mLruCache.remove(url);
- mLruCache.put(url, bitmap);
- return bitmap;
- }
- }
- // 如果硬引用缓存中找不到,到软引用缓存中找
- synchronized (mSoftCache) {
- SoftReference<Bitmap> bitmapReference = mSoftCache.get(url);
- if (bitmapReference !=null) {
- bitmap = bitmapReference.get();
- if (bitmap !=null) {
- // 将图片移回硬缓存
- mLruCache.put(url, bitmap);
- mSoftCache.remove(url);
- return bitmap;
- } else {
- mSoftCache.remove(url);
- }
- }
- }
- returnnull;
- }
- /**
- * 添加图片到缓存
- */
- publicvoid addBitmapToCache(String url, Bitmap bitmap) {
- if (bitmap !=null) {
- synchronized (mLruCache) {
- mLruCache.put(url, bitmap);
- }
- }
- }
- publicvoid clearCache() {
- mSoftCache.clear();
- }
- }
- //文件缓存,缓存到SD卡上
- public class ImageFileCache {
- private static final String CACHDIR = "ImgCach";
- private static final String WHOLESALE_CONV = ".cach";
- private static final int MB = 1024*1024;
- private static finalint CACHE_SIZE = 10;
- privatestaticfinalintFREE_SD_SPACE_NEEDED_TO_CACHE = 10;
- public ImageFileCache() {
- //清理文件缓存
- removeCache(getDirectory());
- }
- /** 从缓存中获取图片 **/
- public Bitmap getImage(final String url) {
- final String path = getDirectory() +"/" + convertUrlToFileName(url);
- File file = new File(path);
- if (file.exists()) {
- Bitmap bmp = BitmapFactory.decodeFile(path);
- if (bmp == null) {
- file.delete();
- } else {
- updateFileTime(path);
- return bmp;
- }
- }
- return null;
- }
- /** 将图片存入文件缓存 **/
- public void saveBitmap(Bitmap bm, String url) {
- if (bm == null) {
- return;
- }
- //判断sdcard上的空间
- if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
- //SD空间不足
- return;
- }
- String filename = convertUrlToFileName(url);
- String dir = getDirectory();
- File dirFile = new File(dir);
- if (!dirFile.exists())
- dirFile.mkdirs();
- File file = new File(dir +"/" + filename);
- try {
- file.createNewFile();
- OutputStream outStream = new FileOutputStream(file);
- bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
- outStream.flush();
- outStream.close();
- } catch (FileNotFoundException e) {
- Log.w("ImageFileCache","FileNotFoundException");
- } catch (IOException e) {
- Log.w("ImageFileCache","IOException");
- }
- }
- /**
- * 计算存储目录下的文件大小,
- * 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定
- * 那么删除40%最近没有被使用的文件
- */
- private boolean removeCache(String dirPath) {
- File dir = new File(dirPath);
- File[] files = dir.listFiles();
- if (files == null) {
- return true;
- }
- if (!android.os.Environment.getExternalStorageState().equals(
- android.os.Environment.MEDIA_MOUNTED)) {
- return false;
- }
- int dirSize = 0;
- for (int i = 0; i < files.length; i++) {
- if (files[i].getName().contains(WHOLESALE_CONV)) {
- dirSize += files[i].length();
- }
- }
- if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
- int removeFactor = (int) ((0.4 * files.length) + 1);
- Arrays.sort(files, new FileLastModifSort());
- for (int i = 0; i < removeFactor; i++) {
- if (files[i].getName().contains(WHOLESALE_CONV)) {
- files[i].delete();
- }
- }
- }
- if (freeSpaceOnSd() <= CACHE_SIZE) {
- return false;
- }
- return true;
- }
- /** 修改文件的最后修改时间 **/
- public void updateFileTime(String path) {
- File file = new File(path);
- long newModifiedTime = System.currentTimeMillis();
- file.setLastModified(newModifiedTime);
- }
- /** 计算sdcard上的剩余空间 **/
- private int freeSpaceOnSd() {
- StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
- double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) /MB;
- return (int) sdFreeMB;
- }
- /** 将url转成文件名 **/
- private String convertUrlToFileName(String url) {
- String[] strs = url.split("/");
- return strs[strs.length - 1] +WHOLESALE_CONV;
- }
- /** 获得缓存目录 **/
- private String getDirectory() {
- String dir = getSDPath() + "/" +CACHDIR;
- return dir;
- }
- /** 取SD卡路径 **/
- private String getSDPath() {
- File sdDir = null;
- boolean sdCardExist = Environment.getExternalStorageState().equals(
- android.os.Environment.MEDIA_MOUNTED); //判断sd卡是否存在
- if (sdCardExist) {
- sdDir = Environment.getExternalStorageDirectory(); //获取根目录
- }
- if (sdDir != null) {
- return sdDir.toString();
- } else {
- return "";
- }
- }
- /**
- * 根据文件的最后修改时间进行排序
- */
- private class FileLastModifSort implements Comparator<File> {
- public int compare(File arg0, File arg1) {
- if (arg0.lastModified() > arg1.lastModified()) {
- return 1;
- } else if (arg0.lastModified() == arg1.lastModified()) {
- return 0;
- } else {
- return -1;
- }
- }
- }
- }
- //从网络加载图片
- public class ImageGetFromHttp {
- private static final String LOG_TAG = "ImageGetFromHttp";
- public static Bitmap downloadBitmap(String url) {
- final HttpClient client = new DefaultHttpClient();
- final HttpGet getRequest = new HttpGet(url);
- try {
- HttpResponse response = client.execute(getRequest);
- final int statusCode = response.getStatusLine().getStatusCode();
- if (statusCode != HttpStatus.SC_OK) {
- Log.w(LOG_TAG, "Error " + statusCode + " while retrieving bitmap from " + url);
- return null;
- }
- final HttpEntity entity = response.getEntity();
- if (entity != null) {
- InputStream inputStream = null;
- try {
- inputStream = entity.getContent();
- FilterInputStream fit = new FlushedInputStream(inputStream);
- return BitmapFactory.decodeStream(fit);
- } finally {
- if (inputStream !=null) {
- inputStream.close();
- inputStream = null;
- }
- entity.consumeContent();
- }
- }
- } catch (IOException e) {
- getRequest.abort();
- Log.w(LOG_TAG,"I/O error while retrieving bitmap from " + url, e);
- } catch (IllegalStateException e) {
- getRequest.abort();
- Log.w(LOG_TAG, "Incorrect URL: " + url);
- } catch (Exception e) {
- getRequest.abort();
- Log.w(LOG_TAG,"Error while retrieving bitmap from " + url, e);
- } finally {
- client.getConnectionManager().shutdown();
- }
- return null;
- }
- /*
- * An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
- */
- static class FlushedInputStream extends FilterInputStream {
- public FlushedInputStream(InputStream inputStream) {
- super(inputStream);
- }
- @Override
- public long skip(long n) throws IOException {
- long totalBytesSkipped = 0L;
- while (totalBytesSkipped < n) {
- long bytesSkipped = in.skip(n - totalBytesSkipped);
- if (bytesSkipped == 0L) {
- int b = read();
- if (b < 0) {
- break; // we reached EOF
- } else {
- bytesSkipped = 1; // we read one byte
- }
- }
- totalBytesSkipped += bytesSkipped;
- }
- return totalBytesSkipped;
- }
- }
- }
- //=============================获取图片========================================
- /*** 获得一张图片,从三个地方获取,首先是内存缓存,然后是文件缓存,最后从网络获取 ***/
- public Bitmap getBitmap(String url) {
- // 从内存缓存中获取图片
- Bitmap result = memoryCache.getBitmapFromCache(url);
- if (result ==null) {
- // 文件缓存中获取
- result = fileCache.getImage(url);
- if (result ==null) {
- // 从网络获取
- result = ImageGetFromHttp.downloadBitmap(url);
- if (result !=null) {
- fileCache.saveBitmap(result, url);
- memoryCache.addBitmapToCache(url, result);
- }
- } else {
- // 添加到内存缓存
- memoryCache.addBitmapToCache(url, result);
- }
- }
- return result;
来源: http://www.phpxs.com/code/1002051/