我们在RecyclerView中大量显示ImageView图片的时候,会发现从本地加载图片显示在ImageView特别的慢,甚至会内存溢出,这个时候我们可以使用LruCache来缓存本地图片bitmap数据,这样在加载时就会特别快了。
下面是LruCache图片缓存的方法。永远不用担心Bitmap导致内存溢出,因为LruCache使用的是你系统的剩余内存,你可以自己分配多少内存给它,代码如下:
package com.xuanyin.homektv.util; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Handler; import android.os.Environment; import android.widget.ImageView; import android.util.LruCache; import java.util.LinkedHashMap; import java.util.concurrent.ExecutorService; import java.util.Map; import java.util.concurrent.Executors; import java.io.File; public class ImageUtils { private static LruCache<String, Bitmap> mCaches; /** * 定义上下文对象 */ private Context mContext; private static Handler mHandler; //声明线程池,全局只有一个线程池,所有访问网络图片,只有这个池子去访问。 private static ExecutorService mPool; //解决错位问题,定义一个存标记的集合 private Map<ImageView, String> mTags = new LinkedHashMap<ImageView, String>(); public ImageUtils(Context context) { this.mContext = context; if (mCaches == null) { //申请内存空间 int maxSize = (int) (Runtime.getRuntime().freeMemory() / 4); //实例化LruCache mCaches = new LruCache<String, Bitmap>(maxSize) { @Override protected int sizeOf(String key, Bitmap value) { //判断添加进入的value的占用内存的大小 //这里默认sizeOf是返回1,不占用,内存会不够用,所以要给它一个具体占用内存的大小 //return super.sizeOf(key, value); //获取Bitmap的大小 return value.getRowBytes() * value.getHeight(); } }; } if (mHandler == null) { //实例化Handler mHandler = new Handler(); } if (mPool == null) { //创建固定大小的线程池 mPool = Executors.newFixedThreadPool(3); //创建一个缓存的线程池,生产者和消费者,一个线程生产,必须得消费完成后再生产 /*Executors.newCachedThreadPool(); Executors.newSingleThreadExecutor();//创建一个单线程池 Executors.newScheduledThreadPool();//创建一个计划的任务池*/ } } /** * 给imageView加载url对应的图片 * * @param iv * @param url */ public void display(ImageView iv, String url) { System.out.println("加载url对应的图片:" + url); //1.从内存中获取 Bitmap bitmap = mCaches.get(url); if (bitmap != null) { //内存中有,显示图片 iv.setImageBitmap(bitmap); System.out.println("加载url内存图片:" + url); return; } //2.内存中没有,从本地获取 bitmap = loadFromLocal(url); if (bitmap != null) { //本地有,显示 iv.setImageBitmap(bitmap); return; } } /** * 从本地获取图片 * * @param url * @return bitmap */ private Bitmap loadFromLocal(String url) { //本地需要存储路径 //File file = getCacheFile(url); File file = new File(url); if (file.exists()) { //本地有 //把文件解析成Bitmap Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); //存储到内存 mCaches.put(url, bitmap); return bitmap; } return null; } /** * 获取缓存文件路径(缓存目录) * * @return 缓存的文件 */ private File getCacheFile(String url) { //获取当前的状态,Environment是环境变量 String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { //挂载状态,sd卡存在 File dir = new File(Environment.getExternalStorageDirectory(), "/Android/data/" + mContext.getPackageName() + "/icon"); if (!dir.exists()) { //文件不存在,就创建 dir.mkdirs(); } //此处的url可能会很长,一般会使用md5加密 return new File(dir, url); } else { File dir = new File(mContext.getCacheDir(), "/icon"); if (!dir.exists()) { //文件不存在,就创建 dir.mkdirs(); } return new File(dir, url); } } }
我们在RecyclerView中如果要显示图片,可以类似如下即可:
ImageUtils imageUtils = new ImageUtils(getContext()); imageUtils.display(imageView, "xxx.jpg");
小编发现Android中使用LruCache来缓存并显示图片,速度特别的快,比那个Glide快多了。