android 实现图片的三级缓存工具类

大家在做项目时有可能会对图片做一些缓存,不必重复的请求数据。图片的缓存有三级,一是软件的内存中,二是手机中的SD卡,最后才是我们的网络请求,其实这点不算缓存。暂且把它归纳进来吧!这个图片缓存的思路是这样的:1.一级缓存在cache集合中用KEY值查找有:显示否则进入二级查找。2.二级缓存在本地SD卡中是否有图片路径,有:显示并添加到一级缓存,否:进入三级请求。3.三级缓存通过URL网络请求加载,有:显示并添加到一二级缓存中,否则显示错误加载图片。按着这个思路往下做就轻松了,比较简单的一种实现方法,就直接贴代码:

public class ImageLoadCache {
    private Context context;
    private int loadingRes; //加载中的图片
    private int ErroRes;   //加载失败的图片
    private Map<String, Bitmap> cache = new HashMap<>(); //内存缓存集合

    ImageLoadCache(Context context, int loadingRes, int ErroRes) {
        this.context = context;
        this.loadingRes = loadingRes;
        this.ErroRes = ErroRes;
    }

    public void LoadImge(String Imgpath, ImageView view) {
        view.setTag(Imgpath); //给最新的ImageView设置最新图片路径的标识
        Bitmap bitmap = null;
        //一级缓存
        bitmap = getFirstBitmap(Imgpath);
        if (bitmap != null) {
            view.setImageBitmap(bitmap);
            return;
        }
        //二级缓存
        bitmap = getSecondBitmap(Imgpath);
        if (bitmap != null) {
            view.setImageBitmap(bitmap);
            cache.put(Imgpath, bitmap);
            return;
        }
        //三级分线程
        getThreeBitmap(Imgpath, view);
    }

    public Bitmap getSecondBitmap(String Imgpath) {
        //二级缓存,可以再这里判断手机是否有SD卡
        String SdPath = context.getExternalFilesDir(null).getAbsolutePath();
        String subPath = Imgpath.substring(Imgpath.lastIndexOf("/") + 1);
        String filePath = SdPath + "/" + subPath;
        return BitmapFactory.decodeFile(filePath);
    }

    public Bitmap getFirstBitmap(String Imgpath) {
        return cache.get(Imgpath);
    }

    public void getThreeBitmap(final String Imgpath, final ImageView view) {
        final String newPathImg = (String) view.getTag();
        new AsyncTask<Void, Void, Bitmap>() {
            //联网请求得到bitmap对象
            @Override
            protected Bitmap doInBackground(Void... params) {
                //在分线程执行, 可能需要等待一定时间才会执行
                //在等待的过程中imageView中的tag值就有可能改变了
                //如果改变了, 就不应该再去加载图片(此图片此时不需要显示)就直接返回null
                Bitmap bitmap = null;
                try {
                    if (newPathImg != Imgpath) {
                        return null;
                    }
                    //得到连接
                    URL url = new URL(Imgpath);
                    HttpURLConnection connect = (HttpURLConnection) url.openConnection();
                    //设置
                    connect.setReadTimeout(5000);
                    connect.setConnectTimeout(5000);
                    //连接
                    connect.connect();
                    //发请求读取返回的数据并封装为bitmap
                    int responseCode = connect.getResponseCode();
                    if (responseCode == 200) {
                        InputStream is = connect.getInputStream();//获取图片流
                        bitmap = BitmapFactory.decodeStream(is);
                        is.close(); //流关闭
                        if (bitmap != null) {
                            //缓存到一级缓存(分线程)
                            cache.put(Imgpath, bitmap);
                            //缓存到二级缓存(分线程)
                            String SdPath = context.getExternalFilesDir(null).getAbsolutePath();
                            String subPath = Imgpath.substring(Imgpath.lastIndexOf("/") + 1);
                            String filePath = SdPath + "/" + subPath;
                            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(filePath));//通过压缩的方式存入
                        }
                    }
                    connect.disconnect(); //断开连接
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return bitmap;
            }

            @Override
            protected void onPreExecute() {
                view.setImageResource(loadingRes);
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                //这里也要判断是否为当前的图片路径,否则直接返回
                String newPathImgs = (String) view.getTag();
                if (newPathImgs != Imgpath) {
                    return;
                }
                if (bitmap == null) {
                    view.setImageResource(ErroRes);
                } else {
                    view.setImageBitmap(bitmap);
                }
            }
        }.execute();
    }
}
在这里设置了一个view的标识符,主要是判断传入进来的图片路径和当前的view是否相等,这种情况在listview中item复用的时候会出现,如果不加这个标识则会出现图片加载过程中的闪现。这个原因就是item复用时imgeview加载的是不同的图片路径,所以就会当不同路径不同的 imgeview就直接return掉,所以这个添加view的标识符是相当重要的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值