android三级缓存详解

来源:互联网 发布:inventor软件怎么样 编辑:程序博客网 时间:2024/06/05 21:09

为什么需要图片缓存

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;        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115

本地缓存

两个方法:设置本地缓存,获取本地缓存
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();            }        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

内存缓存

两个方法:设置内存缓存,获取内存缓存问题:    如果使用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);            }        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

图片压缩

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

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

0 0
原创粉丝点击