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

来源:互联网 发布:java socket 发送数据 编辑:程序博客网 时间:2024/06/05 07:19

大家在做项目时有可能会对图片做一些缓存,不必重复的请求数据。图片的缓存有三级,一是软件的内存中,二是手机中的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 0
原创粉丝点击