android三级缓存详解

来源:互联网 发布:考勤机软件下载 编辑:程序博客网 时间:2024/05/16 15:08

为什么需要图片缓存

android默认给每个应用只分配16M的内存,所以如果加载过多的图片,为了防止内存溢出,应该将图片缓存起来。图片的三级缓存分别是:    内存缓存    本地缓存    网络缓存其中,内存缓存应优先加载,它速度最快;本地缓存次优先加载,它速度也快;网络缓存不应该优先加载,它走网络,速度慢且耗流量。(总的来说由快到慢)

三级缓存的具体实现
网络缓存

    根据图片的url去加载图片    在本地和内存中缓存    public class NetCacheUtils {        private LocalCacheUtils mLocalCacheUtils;        private MemoryCacheUtils mMemoryCacheUtils;        public NetCacheUtils(LocalCacheUtils localCacheUtils,                MemoryCacheUtils memoryCacheUtils) {            mLocalCacheUtils = localCacheUtils;            mMemoryCacheUtils = memoryCacheUtils;        }        /**         * 从网络下载图片         *          * @param ivPic         * @param url         */        public void getBitmapFromNet(ImageView ivPic, String url) {            new BitmapTask().execute(ivPic, url);// 启动AsyncTask,                                                    // 参数会在doInbackground中获取        }        /**         * Handler和线程池的封装         *          * 第一个泛型: 参数类型 第二个泛型: 更新进度的泛型, 第三个泛型是onPostExecute的返回结果         *          *          */        class BitmapTask extends AsyncTask<Object, Void, Bitmap> {            private ImageView ivPic;            private String url;            /**             * 后台耗时方法在此执行, 子线程             */            @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 onProgressUpdate(Void... values) {                super.onProgressUpdate(values);            }            /**             * 耗时方法结束后,执行该方法, 主线程             */            @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);// 将图片保存在内存                        System.out.println("从网络缓存读取图片啦...");                    }                }            }        }        /**         * 下载图片         *          * @param url         * @return         */        private 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 option = new BitmapFactory.Options();                    option.inSampleSize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定                    option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图片格式                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);                    return bitmap;                }            } catch (Exception e) {                e.printStackTrace();            } finally {                conn.disconnect();            }            return null;        }    }

本地缓存

两个方法:设置本地缓存,获取本地缓存
public class LocalCacheUtils {        public static final String CACHE_PATH = Environment                .getExternalStorageDirectory().getAbsolutePath() + "/local_cache";        /**         * 从本地sdcard读图片         */        public Bitmap getBitmapFromLocal(String url) {            try {                String fileName = MD5Encoder.encode(url);                File file = new File(CACHE_PATH, fileName);                if (file.exists()) {                    Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(                            file));                    return bitmap;                }            } catch (Exception e) {                e.printStackTrace();            }            return null;        }        /**         * 向sdcard写图片         *          * @param url         * @param bitmap         */        public void setBitmapToLocal(String url, Bitmap bitmap) {            try {                String fileName = MD5Encoder.encode(url);                File file = new File(CACHE_PATH, fileName);                File parentFile = file.getParentFile();                if (!parentFile.exists()) {// 如果文件夹不存在, 创建文件夹                    parentFile.mkdirs();                }                // 将图片保存在本地                bitmap.compress(CompressFormat.JPEG, 100,                        new FileOutputStream(file));            } catch (Exception e) {                e.printStackTrace();            }        }    }

内存缓存

两个方法:设置内存缓存,获取内存缓存问题:    如果使用HashMap存储图片时,当图片越来越多时,会导致内存溢出,因为它是强引用,java的垃圾回收器不会回收。    如若改成软引用SoftReference(内存不够时,垃圾回收器会考虑回收),仍有一个问题:在android2.3+, 系统会优先将SoftReference的对象提前回收掉, 即使内存够用。解决办法:可以用LruCache来解决上述内存不回收或提前回收的问题。least recentlly use 最少最近使用算法 它会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定
 public class MemoryCacheUtils {            // private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new            // HashMap<String, SoftReference<Bitmap>>();            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             */            public Bitmap getBitmapFromMemory(String url) {                // SoftReference<Bitmap> softReference = mMemoryCache.get(url);                // if (softReference != null) {                // Bitmap bitmap = softReference.get();                // return bitmap;                // }                return mMemoryCache.get(url);            }            /**             * 写内存             *              * @param url             * @param bitmap             */            public void setBitmapToMemory(String url, Bitmap bitmap) {                // SoftReference<Bitmap> softReference = new                // SoftReference<Bitmap>(bitmap);                // mMemoryCache.put(url, softReference);                mMemoryCache.put(url, bitmap);            }        }

图片压缩

//图片压缩处理(在从网络获取图片的时候就进行压缩)    BitmapFactory.Options option = new BitmapFactory.Options();    option.inSampleSize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定    option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图片格式    Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);

转载出处:http://blog.csdn.net/sinat_20645961/article/details/46325243

1 1