Android控件使用篇Android专题

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

2021-04-01  本文已影响0人  千夜零一

介绍

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

主要用法:

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

用法总结

主角登场: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

上一篇下一篇

猜你喜欢

热点阅读