• Android图片缓存之Lru算法(二)


    前言:

         上篇我们总结了Bitmap的处理,同时对比了各种处理的效率以及对内存占用大小。我们得知一个应用如果使用大量图片就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发生的概率呢?之前我们一直在使用SoftReference软引用,SoftReference是一种现在已经不再推荐使用的方式,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用变得不再可靠,所以今天我们来认识一种新的缓存处理算法Lru,然后学习一下基于Lru的Lrucache、DiskLruCache 实现我们的图片缓存。

    Lru:

       LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”,LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉,比如我们缓存10000条数据,当数据小于10000时可以随意添加,当超过10000时就需要把新的数据添加进来,同时要把过期数据删除,以确保我们最大缓存10000条,那怎么确定删除哪条过期数据呢,采用LRU算法实现的话就是将最老的数据删掉。

    基于LruCache实现内存缓存:

     1.)初始化MemoryCache

      这里内存缓存的是Drawable 而不是Bitmap 理由是Drawable相对Bitmap来说有很大的内存优势

     
            int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取系统分配给应用的总内存大小
            int mCacheSize = maxMemory / 8;//设置图片内存缓存占用八分之一
            mMemoryCache = new LruCache<String, Drawable>(mCacheSize) {
                //必须重写此方法,来测量Bitmap的大小
                @Override
                protected int sizeOf(String key, Drawable value) {
                    if (value instanceof BitmapDrawable) {
                        Bitmap bitmap = ((BitmapDrawable) value).getBitmap();
                        return bitmap == null ? 0 : bitmap.getByteCount();
                    }
                    return super.sizeOf(key, value);
                }
            };
     

    2.)添加一个Drawable到内存缓存

     
      /**
         * 添加Drawable到内存缓存
         *
         * @param key
         * @param drawable
         */
        private void addDrawableToMemoryCache(String key, Drawable drawable) {
            if (getDrawableFromMemCache(key) == null && drawable != null) {
                mMemoryCache.put(key, drawable);
            }
        }
     

    3.)从内存缓存中获取一个Drawable

     
        /**
         * 从内存缓存中获取一个Drawable
         *
         * @param key
         * @return
         */
        public Drawable getDrawableFromMemCache(String key) {
            return mMemoryCache.get(key);
        }
     

    4.)从内存缓存中移除一个Drawable

     
       /**
         * 从内存缓存中移除
         *
         * @param key
         */
        public void removeCacheFromMemory(String key) {
            mMemoryCache.remove(key);
        }
     

    5.)清空内存缓存

        /**
         * 清理内存缓存
         */
        public void cleanMemoryCCache() {
            mMemoryCache.evictAll();
        }

    其实Lru缓存机制本质上就是存储在一个LinkedHashMap存储,为了保障插入的数据顺序,方便清理。

    基于DiskLruCache实现磁盘缓存:

       DiskLruCache类并不是谷歌官方实现,需要自行下载,下载地址:https://github.com/JakeWharton/DiskLruCache

      1.)初始化DiskLruCache

     
           File cacheDir = context.getCacheDir();//指定的是数据的缓存地址
            long diskCacheSize = 1024 * 1024 * 30;//最多可以缓存多少字节的数据
            int appVersion = DiskLruUtils.getAppVersion(context);//指定当前应用程序的版本号
            int valueCount = 1;//指定同一个key可以对应多少个缓存文件
            try {
                mDiskCache = DiskLruCache.open(cacheDir, appVersion, valueCount, diskCacheSize);
            } catch (Exception ex) {
            }
     

    2.)写入一个文件到磁盘缓存

     
        /**
         * 添加Bitmap到磁盘缓存
         *
         * @param key
         * @param value
         */
        private void addBitmapToDiskCache(String key, byte[] value) {
            OutputStream out = null;
            try {
                DiskLruCache.Editor editor = mDiskCache.edit(key);
                if (editor != null) {
                    out = editor.newOutputStream(0);
                    if (value != null && value.length > 0) {
                        out.write(value);
                        out.flush();
                        editor.commit();
                    } else {
                        editor.abort();
                    }
                }
                mDiskCache.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                DiskLruUtils.closeQuietly(out);
            }
        }

    3.)从磁盘缓存中读取Drawable

     
        /**
         * 从磁盘缓存中获取一个Drawable
         *
         * @param key
         * @return
         */
        public Drawable getDrawableFromDiskCache(String key) {
            try {
                DiskLruCache.Snapshot snapShot = mDiskCache.get(key);
                if (snapShot != null) {
                    InputStream is = snapShot.getInputStream(0);
                    Bitmap bitmap = BitmapFactory.decodeStream(is);
                    Drawable drawable = DiskLruUtils.bitmap2Drawable(bitmap);
                    //从磁盘中读取到之后 加入内存缓存
                    addDrawableToMemoryCache(key, drawable);
                    return drawable;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
     

    4.)从磁盘缓存中移除

     
        /**
         * 从磁盘缓存中移除
         *
         * @param key
         */
        public void removeCacheFromDisk(String key) {
            try {
                mDiskCache.remove(key);
            } catch (Exception e) {
            }
        }
     

    5.)清空磁盘缓存

     
        /**
         * 清理磁盘缓存
         */
        public void cleanDiskCache() {
            try {
                mDiskCache.delete();
            } catch (Exception e) {
            }
        }
     

    图片下载过程:

       接下来实例中用到了一点RxJava的知识有不了解RxJava的请自行了解一下。

      1.)采用异步方式操作磁盘缓存和网络下载, 内存缓存可以在主线程中操作

     
       public void disPlay(final ImageView imageView, String imageUrl) {
            //生成唯一key
            final String key = DiskLruUtils.hashKeyForDisk(imageUrl);
            //先从内存中读取
            Drawable drawableFromMemCache = getDrawableFromMemCache(key);
            if (drawableFromMemCache != null) {
                imageView.setImageDrawable(drawableFromMemCache);
                return;
            }
            Observable.just(imageUrl)
                    .map(new Func1<String, Drawable>() {
                        @Override
                        public Drawable call(String imageUrl) { // 参数类型 String
                            //从磁盘中读取
                            Drawable drawableFromDiskCache = getDrawableFromDiskCache(key);
                            if (drawableFromDiskCache != null) {
                                return drawableFromDiskCache;
                            }
                            //网络下载
                            return download(imageUrl); // 返回类型 Drawable
                        }
                    })
                    .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
                    .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
                    .subscribe(new Action1<Drawable>() {
                        @Override
                        public void call(Drawable drawable) { // 参数类型 Drawable
                            imageView.setImageDrawable(drawable);
                        }
                    });
        }
     

    2.)下载图片过程以及处理

     
     private Drawable download(String imageUrl) {
            HttpURLConnection urlConnection = null;
            ByteArrayOutputStream bos = null;
            InputStream ins = null;
            try {
                final URL url = new URL(imageUrl);
                urlConnection = (HttpURLConnection) url.openConnection();
                ins = urlConnection.getInputStream();
                bos = new ByteArrayOutputStream();
                int b;
                while ((b = ins.read()) != -1) {
                    bos.write(b);
                }
                bos.flush();
                byte[] bytes = bos.toByteArray();
                Bitmap bitmap = DiskLruUtils.bytes2Bitmap(bytes);
                String key = DiskLruUtils.hashKeyForDisk(imageUrl);
                Drawable drawable = DiskLruUtils.bitmap2Drawable(bitmap);
                //加入内存缓存
                addDrawableToMemoryCache(key, drawable);
                //加入磁盘缓存
                addBitmapToDiskCache(key, bytes);
                return drawable;
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
                DiskLruUtils.closeQuietly(bos);
                DiskLruUtils.closeQuietly(ins);
            }
            return null;
        }
     

    附上最终图片缓存单例简单实现全部代码以及DiskLruUtils工具类代码

    ImageLoadManager.java
    public class ImageLoadManager {
        private LruCache<String, Drawable> mMemoryCache;//内存缓存
        private DiskLruCache mDiskCache;//磁盘缓存
        private static ImageLoadManager mInstance;//获取图片下载单例引用

        /**
         * 构造器
         *
         * @param context
         */
        private ImageLoadManager(Context context) {
            int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取系统分配给应用的总内存大小
            int mCacheSize = maxMemory / 8;//设置图片内存缓存占用八分之一
            mMemoryCache = new LruCache<String, Drawable>(mCacheSize) {
                //必须重写此方法,来测量Bitmap的大小
                @Override
                protected int sizeOf(String key, Drawable value) {
                    if (value instanceof BitmapDrawable) {
                        Bitmap bitmap = ((BitmapDrawable) value).getBitmap();
                        return bitmap == null ? 0 : bitmap.getByteCount();
                    }
                    return super.sizeOf(key, value);
                }
            };

            File cacheDir = context.getCacheDir();//指定的是数据的缓存地址
            long diskCacheSize = 1024 * 1024 * 30;//最多可以缓存多少字节的数据
            int appVersion = DiskLruUtils.getAppVersion(context);//指定当前应用程序的版本号
            int valueCount = 1;//指定同一个key可以对应多少个缓存文件
            try {
                mDiskCache = DiskLruCache.open(cacheDir, appVersion, valueCount, diskCacheSize);
            } catch (Exception ex) {
            }
        }

        /**
         * 获取单例引用
         *
         * @return
         */
        public static ImageLoadManager getInstance(Context context) {
            ImageLoadManager inst = mInstance;
            if (inst == null) {
                synchronized (RequestManager.class) {
                    inst = mInstance;
                    if (inst == null) {
                        inst = new ImageLoadManager(context.getApplicationContext());
                        mInstance = inst;
                    }
                }
            }
            return inst;
        }

        public void disPlay(final ImageView imageView, String imageUrl) {
            //生成唯一key
            final String key = DiskLruUtils.hashKeyForDisk(imageUrl);
            //先从内存中读取
            Drawable drawableFromMemCache = getDrawableFromMemCache(key);
            if (drawableFromMemCache != null) {
                imageView.setImageDrawable(drawableFromMemCache);
                return;
            }
            Observable.just(imageUrl)
                    .map(new Func1<String, Drawable>() {
                        @Override
                        public Drawable call(String imageUrl) { // 参数类型 String
                            //从磁盘中读取
                            Drawable drawableFromDiskCache = getDrawableFromDiskCache(key);
                            if (drawableFromDiskCache != null) {
                                return drawableFromDiskCache;
                            }
                            //网络下载
                            return download(imageUrl); // 返回类型 Drawable
                        }
                    })
                    .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
                    .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
                    .subscribe(new Action1<Drawable>() {
                        @Override
                        public void call(Drawable drawable) { // 参数类型 Drawable
                            imageView.setImageDrawable(drawable);
                        }
                    });
        }


        /**
         * 添加Drawable到内存缓存
         *
         * @param key
         * @param drawable
         */
        private void addDrawableToMemoryCache(String key, Drawable drawable) {
            if (getDrawableFromMemCache(key) == null && drawable != null) {
                mMemoryCache.put(key, drawable);
            }
        }

        /**
         * 从内存缓存中获取一个Drawable
         *
         * @param key
         * @return
         */
        public Drawable getDrawableFromMemCache(String key) {
            return mMemoryCache.get(key);
        }

        /**
         * 从磁盘缓存中获取一个Drawable
         *
         * @param key
         * @return
         */
        public Drawable getDrawableFromDiskCache(String key) {
            try {
                DiskLruCache.Snapshot snapShot = mDiskCache.get(key);
                if (snapShot != null) {
                    InputStream is = snapShot.getInputStream(0);
                    Bitmap bitmap = BitmapFactory.decodeStream(is);
                    Drawable drawable = DiskLruUtils.bitmap2Drawable(bitmap);
                    //从磁盘中读取到之后 加入内存缓存
                    addDrawableToMemoryCache(key, drawable);
                    return drawable;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        /**
         * 添加Bitmap到磁盘缓存
         *
         * @param key
         * @param value
         */
        private void addBitmapToDiskCache(String key, byte[] value) {
            OutputStream out = null;
            try {
                DiskLruCache.Editor editor = mDiskCache.edit(key);
                if (editor != null) {
                    out = editor.newOutputStream(0);
                    if (value != null && value.length > 0) {
                        out.write(value);
                        out.flush();
                        editor.commit();
                    } else {
                        editor.abort();
                    }
                }
                mDiskCache.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                DiskLruUtils.closeQuietly(out);
            }
        }

        private Drawable download(String imageUrl) {
            HttpURLConnection urlConnection = null;
            ByteArrayOutputStream bos = null;
            InputStream ins = null;
            try {
                final URL url = new URL(imageUrl);
                urlConnection = (HttpURLConnection) url.openConnection();
                ins = urlConnection.getInputStream();
                bos = new ByteArrayOutputStream();
                int b;
                while ((b = ins.read()) != -1) {
                    bos.write(b);
                }
                bos.flush();
                byte[] bytes = bos.toByteArray();
                Bitmap bitmap = DiskLruUtils.bytes2Bitmap(bytes);
                String key = DiskLruUtils.hashKeyForDisk(imageUrl);
                Drawable drawable = DiskLruUtils.bitmap2Drawable(bitmap);
                //加入内存缓存
                // addDrawableToMemoryCache(key, drawable);
                //加入磁盘缓存
                addBitmapToDiskCache(key, bytes);
                return drawable;
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
                DiskLruUtils.closeQuietly(bos);
                DiskLruUtils.closeQuietly(ins);
            }
            return null;
        }

        /**
         * 从缓存中移除
         *
         * @param key
         */
        public void removeCache(String key) {
            removeCacheFromMemory(key);
            removeCacheFromDisk(key);
        }

        /**
         * 从内存缓存中移除
         *
         * @param key
         */
        public void removeCacheFromMemory(String key) {
            mMemoryCache.remove(key);
        }

        /**
         * 从磁盘缓存中移除
         *
         * @param key
         */
        public void removeCacheFromDisk(String key) {
            try {
                mDiskCache.remove(key);
            } catch (Exception e) {
            }
        }

        /**
         * 磁盘缓存大小
         *
         * @return
         */
        public long diskCacheSize() {

            return mDiskCache.size();
        }

        /**
         * 内存缓存大小
         *
         * @return
         */
        public long memoryCacheSize() {

            return mMemoryCache.size();
        }

        /**
         * 关闭磁盘缓存
         */
        public void closeDiskCache() {
            try {
                mDiskCache.close();
            } catch (Exception e) {
            }
        }

        /**
         * 清理缓存
         */
        public void cleanCache() {
            cleanMemoryCCache();
            cleanDiskCache();
        }

        /**
         * 清理磁盘缓存
         */
        public void cleanDiskCache() {
            try {
                mDiskCache.delete();
            } catch (Exception e) {
            }
        }

        /**
         * 清理内存缓存
         */
        public void cleanMemoryCCache() {
            mMemoryCache.evictAll();
        }
    }

    ImageLoadManager.java
    复制代码
    public class ImageLoadManager {
        private LruCache<String, Drawable> mMemoryCache;//内存缓存
        private DiskLruCache mDiskCache;//磁盘缓存
        private static ImageLoadManager mInstance;//获取图片下载单例引用
    
        /**
         * 构造器
         *
         * @param context
         */
        private ImageLoadManager(Context context) {
            int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取系统分配给应用的总内存大小
            int mCacheSize = maxMemory / 8;//设置图片内存缓存占用八分之一
            mMemoryCache = new LruCache<String, Drawable>(mCacheSize) {
                //必须重写此方法,来测量Bitmap的大小
                @Override
                protected int sizeOf(String key, Drawable value) {
                    if (value instanceof BitmapDrawable) {
                        Bitmap bitmap = ((BitmapDrawable) value).getBitmap();
                        return bitmap == null ? 0 : bitmap.getByteCount();
                    }
                    return super.sizeOf(key, value);
                }
            };
    
            File cacheDir = context.getCacheDir();//指定的是数据的缓存地址
            long diskCacheSize = 1024 * 1024 * 30;//最多可以缓存多少字节的数据
            int appVersion = DiskLruUtils.getAppVersion(context);//指定当前应用程序的版本号
            int valueCount = 1;//指定同一个key可以对应多少个缓存文件
            try {
                mDiskCache = DiskLruCache.open(cacheDir, appVersion, valueCount, diskCacheSize);
            } catch (Exception ex) {
            }
        }
    
        /**
         * 获取单例引用
         *
         * @return
         */
        public static ImageLoadManager getInstance(Context context) {
            ImageLoadManager inst = mInstance;
            if (inst == null) {
                synchronized (RequestManager.class) {
                    inst = mInstance;
                    if (inst == null) {
                        inst = new ImageLoadManager(context.getApplicationContext());
                        mInstance = inst;
                    }
                }
            }
            return inst;
        }
    
        public void disPlay(final ImageView imageView, String imageUrl) {
            //生成唯一key
            final String key = DiskLruUtils.hashKeyForDisk(imageUrl);
            //先从内存中读取
            Drawable drawableFromMemCache = getDrawableFromMemCache(key);
            if (drawableFromMemCache != null) {
                imageView.setImageDrawable(drawableFromMemCache);
                return;
            }
            Observable.just(imageUrl)
                    .map(new Func1<String, Drawable>() {
                        @Override
                        public Drawable call(String imageUrl) { // 参数类型 String
                            //从磁盘中读取
                            Drawable drawableFromDiskCache = getDrawableFromDiskCache(key);
                            if (drawableFromDiskCache != null) {
                                return drawableFromDiskCache;
                            }
                            //网络下载
                            return download(imageUrl); // 返回类型 Drawable
                        }
                    })
                    .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
                    .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
                    .subscribe(new Action1<Drawable>() {
                        @Override
                        public void call(Drawable drawable) { // 参数类型 Drawable
                            imageView.setImageDrawable(drawable);
                        }
                    });
        }
    
    
        /**
         * 添加Drawable到内存缓存
         *
         * @param key
         * @param drawable
         */
        private void addDrawableToMemoryCache(String key, Drawable drawable) {
            if (getDrawableFromMemCache(key) == null && drawable != null) {
                mMemoryCache.put(key, drawable);
            }
        }
    
        /**
         * 从内存缓存中获取一个Drawable
         *
         * @param key
         * @return
         */
        public Drawable getDrawableFromMemCache(String key) {
            return mMemoryCache.get(key);
        }
    
        /**
         * 从磁盘缓存中获取一个Drawable
         *
         * @param key
         * @return
         */
        public Drawable getDrawableFromDiskCache(String key) {
            try {
                DiskLruCache.Snapshot snapShot = mDiskCache.get(key);
                if (snapShot != null) {
                    InputStream is = snapShot.getInputStream(0);
                    Bitmap bitmap = BitmapFactory.decodeStream(is);
                    Drawable drawable = DiskLruUtils.bitmap2Drawable(bitmap);
                    //从磁盘中读取到之后 加入内存缓存
                    addDrawableToMemoryCache(key, drawable);
                    return drawable;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 添加Bitmap到磁盘缓存
         *
         * @param key
         * @param value
         */
        private void addBitmapToDiskCache(String key, byte[] value) {
            OutputStream out = null;
            try {
                DiskLruCache.Editor editor = mDiskCache.edit(key);
                if (editor != null) {
                    out = editor.newOutputStream(0);
                    if (value != null && value.length > 0) {
                        out.write(value);
                        out.flush();
                        editor.commit();
                    } else {
                        editor.abort();
                    }
                }
                mDiskCache.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                DiskLruUtils.closeQuietly(out);
            }
        }
    
        private Drawable download(String imageUrl) {
            HttpURLConnection urlConnection = null;
            ByteArrayOutputStream bos = null;
            InputStream ins = null;
            try {
                final URL url = new URL(imageUrl);
                urlConnection = (HttpURLConnection) url.openConnection();
                ins = urlConnection.getInputStream();
                bos = new ByteArrayOutputStream();
                int b;
                while ((b = ins.read()) != -1) {
                    bos.write(b);
                }
                bos.flush();
                byte[] bytes = bos.toByteArray();
                Bitmap bitmap = DiskLruUtils.bytes2Bitmap(bytes);
                String key = DiskLruUtils.hashKeyForDisk(imageUrl);
                Drawable drawable = DiskLruUtils.bitmap2Drawable(bitmap);
                //加入内存缓存
                // addDrawableToMemoryCache(key, drawable);
                //加入磁盘缓存
                addBitmapToDiskCache(key, bytes);
                return drawable;
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
                DiskLruUtils.closeQuietly(bos);
                DiskLruUtils.closeQuietly(ins);
            }
            return null;
        }
    
        /**
         * 从缓存中移除
         *
         * @param key
         */
        public void removeCache(String key) {
            removeCacheFromMemory(key);
            removeCacheFromDisk(key);
        }
    
        /**
         * 从内存缓存中移除
         *
         * @param key
         */
        public void removeCacheFromMemory(String key) {
            mMemoryCache.remove(key);
        }
    
        /**
         * 从磁盘缓存中移除
         *
         * @param key
         */
        public void removeCacheFromDisk(String key) {
            try {
                mDiskCache.remove(key);
            } catch (Exception e) {
            }
        }
    
        /**
         * 磁盘缓存大小
         *
         * @return
         */
        public long diskCacheSize() {
    
            return mDiskCache.size();
        }
    
        /**
         * 内存缓存大小
         *
         * @return
         */
        public long memoryCacheSize() {
    
            return mMemoryCache.size();
        }
    
        /**
         * 关闭磁盘缓存
         */
        public void closeDiskCache() {
            try {
                mDiskCache.close();
            } catch (Exception e) {
            }
        }
    
        /**
         * 清理缓存
         */
        public void cleanCache() {
            cleanMemoryCCache();
            cleanDiskCache();
        }
    
        /**
         * 清理磁盘缓存
         */
        public void cleanDiskCache() {
            try {
                mDiskCache.delete();
            } catch (Exception e) {
            }
        }
    
        /**
         * 清理内存缓存
         */
        public void cleanMemoryCCache() {
            mMemoryCache.evictAll();
        }
    }
    复制代码
    DiskLruUtils.java
    final class DiskLruUtils {

        /**
         * 关闭输入输出流
         */
        public static void closeQuietly(/*Auto*/Closeable closeable) {
            if (closeable != null) {
                try {
                    closeable.close();
                } catch (RuntimeException rethrown) {
                    throw rethrown;
                } catch (Exception ignored) {
                }
            }
        }

        /**
         * 获取versionCode
         */
        public static int getAppVersion(Context context) {
            try {
                PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
                return info.versionCode;
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            return 1;
        }


        public static String hashKeyForDisk(String key) {
            String cacheKey;
            try {
                final MessageDigest mDigest = MessageDigest.getInstance("MD5");
                mDigest.update(key.getBytes());
                cacheKey = bytesToHexString(mDigest.digest());
            } catch (NoSuchAlgorithmException e) {
                cacheKey = String.valueOf(key.hashCode());
            }
            return cacheKey;
        }

        public static String bytesToHexString(byte[] bytes) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(0xFF & bytes[i]);
                if (hex.length() == 1) {
                    sb.append('0');
                }
                sb.append(hex);
            }
            return sb.toString();
        }

        /**
         * Bitmap → bytes
         */
        public static byte[] bitmap2Bytes(Bitmap bm) {
            if (bm == null) {
                return null;
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
            return baos.toByteArray();
        }

        /**
         * bytes → Bitmap
         */
        public static Bitmap bytes2Bitmap(byte[] bytes) {
            return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        }


        /**
         * Drawable → Bitmap
         */
        public static Bitmap drawable2Bitmap(Drawable drawable) {
            if (drawable == null) {
                return null;
            }
            // 取 drawable 的长宽
            int w = drawable.getIntrinsicWidth();
            int h = drawable.getIntrinsicHeight();
            // 取 drawable 的颜色格式
            Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
            // 建立对应 bitmap
            Bitmap bitmap = Bitmap.createBitmap(w, h, config);
            // 建立对应 bitmap 的画布
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, w, h);
            // 把 drawable 内容画到画布中
            drawable.draw(canvas);
            return bitmap;
        }

        /*
             * Bitmap → Drawable
             */
        public static Drawable bitmap2Drawable(Bitmap bm) {
            if (bm == null) {
                return null;
            }
            BitmapDrawable bd = new BitmapDrawable(bm);
            bd.setTargetDensity(bm.getDensity());
            return new BitmapDrawable(bm);
        }

    }

    DiskLruUtils.java
    复制代码
    final class DiskLruUtils {
    
        /**
         * 关闭输入输出流
         */
        public static void closeQuietly(/*Auto*/Closeable closeable) {
            if (closeable != null) {
                try {
                    closeable.close();
                } catch (RuntimeException rethrown) {
                    throw rethrown;
                } catch (Exception ignored) {
                }
            }
        }
    
        /**
         * 获取versionCode
         */
        public static int getAppVersion(Context context) {
            try {
                PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
                return info.versionCode;
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            return 1;
        }
    
    
        public static String hashKeyForDisk(String key) {
            String cacheKey;
            try {
                final MessageDigest mDigest = MessageDigest.getInstance("MD5");
                mDigest.update(key.getBytes());
                cacheKey = bytesToHexString(mDigest.digest());
            } catch (NoSuchAlgorithmException e) {
                cacheKey = String.valueOf(key.hashCode());
            }
            return cacheKey;
        }
    
        public static String bytesToHexString(byte[] bytes) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(0xFF & bytes[i]);
                if (hex.length() == 1) {
                    sb.append('0');
                }
                sb.append(hex);
            }
            return sb.toString();
        }
    
        /**
         * Bitmap → bytes
         */
        public static byte[] bitmap2Bytes(Bitmap bm) {
            if (bm == null) {
                return null;
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
            return baos.toByteArray();
        }
    
        /**
         * bytes → Bitmap
         */
        public static Bitmap bytes2Bitmap(byte[] bytes) {
            return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        }
    
    
        /**
         * Drawable → Bitmap
         */
        public static Bitmap drawable2Bitmap(Drawable drawable) {
            if (drawable == null) {
                return null;
            }
            // 取 drawable 的长宽
            int w = drawable.getIntrinsicWidth();
            int h = drawable.getIntrinsicHeight();
            // 取 drawable 的颜色格式
            Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
            // 建立对应 bitmap
            Bitmap bitmap = Bitmap.createBitmap(w, h, config);
            // 建立对应 bitmap 的画布
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, w, h);
            // 把 drawable 内容画到画布中
            drawable.draw(canvas);
            return bitmap;
        }
    
        /*
             * Bitmap → Drawable
             */
        public static Drawable bitmap2Drawable(Bitmap bm) {
            if (bm == null) {
                return null;
            }
            BitmapDrawable bd = new BitmapDrawable(bm);
            bd.setTargetDensity(bm.getDensity());
            return new BitmapDrawable(bm);
        }
    
    }
    复制代码

    总结:

     以上就是基于Lru图片缓存简单实现

  • 相关阅读:
    第08组 Beta冲刺 (3/5)
    第08组 Beta冲刺 (2/5)
    第08组 Beta冲刺 (1/5)
    软工实践个人总结
    实验 7:OpenDaylight 实验——Python 中的 REST API 调用
    实验 6:OpenDaylight 实验——OpenDaylight 及 Postman 实现流表下发
    2020软工第二次结对作业
    实验 5 : OpenFlow 协议分析和 OpenDaylight 安装
    2020软工第一次结对作业
    实验 4:Open vSwitch 实验——Mininet 中使用 OVS 命令
  • 原文地址:https://www.cnblogs.com/android-blogs/p/5737582.html
Copyright © 2020-2023  润新知