美文网首页Android控件使用篇Android专题
Glide图片加载的用法介绍和三级缓存实现

Glide图片加载的用法介绍和三级缓存实现

作者: 千夜零一 | 来源:发表于2021-04-01 16:06 被阅读0次

介绍

Glide库是用来实现图片加载的框架,功能强大且易使用,深受大家喜爱。

  • Glide 是一款由 Bump Technologies 开发的图片加载框架。

  • Glide 是适用于 Android 的快速有效的开源媒体管理和图像加载框架,它将媒体解码,内存和磁盘缓存以及资源池包装到一个简单易用的界面中。

  • Glide 支持获取,解码和显示视频静止图像,图像和动画 GIF。

  • Glide 包含灵活的 API,允许开发人员插入几乎所有网络堆栈。

  • 默认情况下,Glide 使用基于自定义 HttpUrlConnection 的堆栈,但还包含实用程序库,它们可以插入 Google 的 Volley 项目或 Square 的 OkHttp 库。

主要用法:

Glide.with(this)
         .load(url)  //图片的网络路径
         .placeholder(R.drawable.loading) //占位图,没加载出来url时展示
         .into(IvImageView);  //布局中的控件

用法总结

  • 先with(),再load(),最后into()

  • Glide 自动缓存在本地,下次再加载直接从本地取

  • Glide 设置加载动图,但是加载静态图片的时候,会加载失败

  • Glide 会自动判断 ImageView 的大小

主角登场:Glide的三级缓存

为啥要做缓存?android默认给每个应用只分配16M的内存,所以如果加载过多的图片,为了防止内存溢出,应该将图片缓存起来。

图片的三级缓存分别是:

1、内存缓存
2、本地缓存
3、网络缓存
其中,内存缓存应优先加载,它速度最快;本地缓存次优先加载,它速度也快;网络缓存不应该优先加载,它走网络,速度慢且耗流量。

最优-优先级:内存缓存 > 本地缓存 > 网络缓存

具体实现:

(1)网络缓存:

两个方法实现:根据图片的url去加载图片、在本地和内存中缓存

//根据图片的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;
    }
}
(2)本地缓存:

两个方法实现:设置本地缓存,以及获取本地缓存

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();
            }
 
        }
}
/**
 * @data on 4/1/21 4:16 PM
 * @auther KC
 * @describe  解URl的码
 */
public class MD5Encoder {
    public static String encode(String string) throws Exception {
        byte[] hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10) {
                hex.append("0");
            }
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString();
    }
}

(3)内存缓存:

两个方法实现:设置内存缓存,获取内存缓存。

 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);
            }
}

Tips:

内存缓存可能产生的问题;

如果使用hashmap去存储图片时,当图片越来越多,那么会造成内存溢出,因为是强引用(对于强引用的系统不会回收)

如果改成软引用softReference,在android 2.3 以上的系统,对象会被提前回收。

解决的办法:

可以用LruCache来解决上述内存不回收或提前回收的问题。least recentlly use 最少最近使用算法 它会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定。(这个东西没有用过..)

参考链接:https://blog.csdn.net/sinat_20645961/article/details/46325243

相关文章

  • Android面试 Glide源码流程

    面试问题 简单介绍一下Glide缓存 具体说说Glide的三级缓存原理 Glide加载一个100x100的图片,是...

  • Glide图片加载的用法介绍和三级缓存实现

    介绍 Glide库是用来实现图片加载的框架,功能强大且易使用,深受大家喜爱。 Glide 是一款由 Bump Te...

  • Glide源码解析(4.X版本)

    知识点汇总: 一:Glide项目概述 二:Glide加载图片的原理 三:Glide三级缓存的设计 四:Glide如...

  • Glide基本用法

    支持版本4.0 基本用法 使用加载中图片和加载错误图片 glide缓存方式 这个diskCacheStrategy...

  • Glide基本使用

    参考 Android图片加载框架最全解析(一),Glide的基本用法Google推荐的图片加载库Glide介绍 思...

  • glide缓存无法更新

    问题 使用glide加载图片,glide有缓存,分为内存缓存和磁盘缓存,可以通过diskCacheStrategy...

  • Android图片加载框架——Glide

    Glide使用教程 Glide是一个快速有效的开源图像加载框架,可实现内存缓存、磁盘缓存,完成对图片资源的加载,汇...

  • Android 图片加载库 Glide的基本用法

    开始 将Glide引入我们的项目 加载图片 基本用法 占位符 普通占位符 错误显示 缓存 取消缓存 指定图片格式 ...

  • Glide实现原理

    一.Glide缓存机制 Glide采取的多级缓存机制,能够较为友好地实现图片、动图的加载。其主要有 内存缓存+磁盘...

  • Glide图片加载框架

    1、Glide图片加载框架三级缓存活动缓存、内存缓存、磁盘缓存第一次:首先去查找顺序活动缓存——》内存缓村———》...

网友评论

    本文标题:Glide图片加载的用法介绍和三级缓存实现

    本文链接:https://www.haomeiwen.com/subject/hibtkltx.html