| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
xg48
10年前发布

Android网络图片缓存

获取一张图片,从三个地方进行获取,首先是内存缓存,然后是文件缓存,最后才从网络中获取。

    //内存缓存    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;