最新消息:关注【太平洋学习网】微信公众号,可以获取全套资料,【全套Java基础27天】【JavaEE就业视频4个月】【Android就业视频4个月】

LruCache缓存本地图片并快速显示图片(ImageView)

Android 太平洋学习网 浏览 评论

我们在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快多了。

来源网站:太平洋学习网,转载请注明出处:http://www.tpyyes.com/a/android/1008.html

与本文相关的文章

发表我的评论
取消评论

表情

您的回复是我们的动力!

  • 昵称 (必填)

网友最新评论