前言:

上篇我们总结了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图片缓存简单实现

Android图片缓存之Lru算法(二)的更多相关文章

  1. Android图片缓存之Lru算法

    前言: 上篇我们总结了Bitmap的处理,同时对比了各种处理的效率以及对内存占用大小.我们得知一个应用如果使用大量图片就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发 ...

  2. android图片缓存框架Android-Universal-Image-Loader(二)

    http://blog.csdn.net/king_is_everyone/article/details/35595515 这篇打算直接告诉大家怎么用吧,其实这个也不是很难的框架,大致使用过程如下: ...

  3. Android图片缓存之Bitmap详解

    前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. 图片缓存相关博客地址: Android图片缓 ...

  4. Android图片缓存之Glide进阶

    前言: 前面学习了Glide的简单使用(Android图片缓存之初识Glide),今天来学习一下Glide稍微复杂一点的使用. 图片缓存相关博客地址: Android图片缓存之Bitmap详解 And ...

  5. Android图片缓存之初识Glide

    前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实 ...

  6. 安卓高级 Android图片缓存之初识Glide

    前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实 ...

  7. Android图片缓存框架Glide

    Android图片缓存框架Glide Glide是Google提供的一个组件.它具有获取.解码和展示视频剧照.图片.动画等功能.它提供了灵活的API,帮助开发者将Glide应用在几乎任何网络协议栈中. ...

  8. Android图片缓存之初识Glide(三)

    前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实 ...

  9. Android 图片缓存处理

    异步下载 / 本地缓存 异步下载 大家都知道,在Android应用中UI线程5秒没响应的话就会抛出无响应异常,对于远程获取大的资源来说,这种异常还是很容易就会抛出来的,那么怎么避免这种问题的产生.在a ...

随机推荐

  1. mongodb v2.4.9 快速操作记录

    参考链接:http://www.runoob.com/mongodb/mongodb-tutorial.html oschina链接:https://gitee.com/dhclly/icedog.s ...

  2. luogu1578 奶牛浴场 枚举点最大子矩阵

    建议看看王知昆dalao的论文,讲得很好 #include <algorithm> #include <iostream> #include <cstring> # ...

  3. 大数据学习——scala集合练习

    package com /** * Created by ZX on 2016/4/5. */ object ListTest { def main(args: Array[String]) { // ...

  4. day05_03 字符串格式化

    pycharm小技巧,一般情况下都需要在代码前注释以下作者以及创建日期 但是如何让软件默认生成呢? 格式化输出 可以用占位符 %s     string的缩写 #__author:Administra ...

  5. linux随笔三

    1.ps   结果输出: PID TTY TIME CMD pts/ :: bash pts/ :: ps显示了程序的进程ID,其运行的终端和进程使用的cpu时间

  6. 2017"百度之星"程序设计大赛 - 复赛

    Arithmetic of Bomb  Accepts: 1050  Submissions: 1762  Time Limit: 2000/1000 MS (Java/Others)  Memory ...

  7. [转]廖雪峰:datetime用法

    datetime是Python处理日期和时间的标准库. 获取当前日期和时间 我们先看如何获取当前日期和时间: >>> from datetime import datetime &g ...

  8. JDBC 学习笔记(六)—— PreparedStatement

    1. 引入 PreparedStatement PreparedStatement 通过 Connection.createPreparedStatement(String sql) 方法创建,主要用 ...

  9. 【bzoj4004】[JLOI2015]装备购买 贪心+高斯消元求线性基

    题目描述 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 <= j < ...

  10. P1023 税收与补贴问题 (模拟)

    题目链接 Solution 比较恶心的模拟题(主要是难看懂题意其实) 题意戳这里 然后根据一些简单的数学常识,可以知道这是一个二次函数. 所以我们每次枚举一个值,然后判定政府给出的价格是否是顶点即可. ...