android 图片缓存,记录一下

来源:互联网 发布:vb编程百度云 编辑:程序博客网 时间:2024/05/21 21:46

多写了点注释而已,没有其他的变化,只有两级,硬引用和软引用,感觉已经够了吧,没用到弱引用

复制代码
public class ImageFileCache {    // 目录名称    private static final String CACHDIR = "ImgCach";    // 图片缓存后缀    private static final String WHOLESALE_CONV = ".cach";    // 10mb    private static final int MB = 1024 * 1024;    // 10张图片    private static final int CACHE_SIZE = 10;    //     private static final int FREE_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) {        // bitmap == null直接返回        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);            // 将该bitmap写入到outStream输出流            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) {        // 以路径dirPath构造File实例        File dir = new File(dirPath);        // 图片文件数组, dir不是路径时,返回null        File[] files = dir.listFiles();        //         if (files == null) {            return true;        }        // sd卡的存储状态必须可读可写,否则返回false        if (!android.os.Environment.getExternalStorageState().equals(                android.os.Environment.MEDIA_MOUNTED)) {            return false;        }        int dirSize = 0;        for (int i = 0; i < files.length; i++) {            // 判断该文件名是否存在WHOLESALE_CONV后缀            // 存在则获取文件长度,长度为0说明文件不存在            if (files[i].getName().contains(WHOLESALE_CONV)) {                dirSize += files[i].length();            }        }                // 如果总文件长度大于CACHE_SIZE * MB(10mb)|| 当前 freeSpaceOnSd() < 10mb        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();                }            }        }        // 如果sd卡剩余空间 <= 10mb        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查询文件系统相关的信息。        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;        // getExternalStorageState() 获得当前外部储存媒体的状态。        // MEDIA_MOUNTED 存储媒体已经挂载,并且挂载点可读/写。        boolean sdCardExist = Environment.getExternalStorageState().equals(                android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在        if (sdCardExist) {            // getExternalStorageDirectory() 获取外部存储媒体目录            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 ImageMemoryCache {    /**     * 从内存读取数据速度是最快的,为了更大限度使用内存,这里使用了两层缓存。     * 硬引用缓存不会轻易被回收,用来保存常用数据,不常用的转入软引用缓存。     */    private static final int SOFT_CACHE_SIZE = 15;  //软引用缓存容量    private static LruCache<String, Bitmap> mLruCache;  //硬引用缓存    private static LinkedHashMap<String, SoftReference<Bitmap>> mSoftCache;  //软引用缓存                                                                                              public ImageMemoryCache(Context context) {        // 通过ActivityManager获取应用的可用内存大小,单位mb        int memClass = ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();        // 硬引用缓存容量        int cacheSize = 1024 * 1024 * memClass / 4;  //硬引用缓存容量,为系统可用内存的1/4                mLruCache = new LruCache<String, Bitmap>(cacheSize) {            @Override            protected int sizeOf(String key, Bitmap value) {                if (value != null)                    return value.getRowBytes() * value.getHeight();                else                    return 0;            }                                                                                                      @Override            protected void 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) {            private static final long serialVersionUID = 6040103833179403725L;            @Override            protected boolean removeEldestEntry(Entry<String, SoftReference<Bitmap>> eldest) {                if (size() > SOFT_CACHE_SIZE){                        return true;                  }                  return false;             }        };    }                                                                                      /**     * 从缓存中获取图片     */    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);                }            }        }        return null;    }                                                                                       /**     * 添加图片到缓存     */    public void addBitmapToCache(String url, Bitmap bitmap) {        if (bitmap != null) {            synchronized (mLruCache) {                mLruCache.put(url, bitmap);            }        }    }                                                                                      public void clearCache() {        mSoftCache.clear();    }}
复制代码

 

复制代码
package bitmap.cache;import java.io.FilterInputStream;import java.io.IOException;import java.io.InputStream;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.HttpStatus;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.util.Log;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 class GetBitmap {    /*** 获得一张图片,从三个地方获取,首先是内存缓存,然后是文件缓存,最后从网络获取 ***/    public static Bitmap getBitmap(String url) {        // 从内存缓存中获取图片        Bitmap result = TestApp.memoryCache.getBitmapFromCache(url);        if (result == null) {            // 文件缓存中获取            result = TestApp.fileCache.getImage(url);            if (result == null) {                // 从网络获取                result = ImageGetFromHttp.downloadBitmap(url);                if (result != null) {                    TestApp.fileCache.saveBitmap(result, url);                    TestApp.memoryCache.addBitmapToCache(url, result);                }            } else {                // 添加到内存缓存                TestApp.memoryCache.addBitmapToCache(url, result);            }        }        return result;    }}
复制代码

 

就这样了啊,要记得用线程加载啊!否则就。。。。。。。。。。。你懂的

原创粉丝点击