Android图片三级缓存原理

缓存原理:

  1. 从集合中读取:集合中没有的时候,走第二个步骤
  2. 访问SD卡或是从缓存目录cache中取,当这里面还没有的时候,走第三个步骤
  3. 访问网络

    以下代码实现了图片缓存原理,并且可以作为一个工具类来使用:
    详情请看代码:

public class ImageCache {

    private LruCache<String, Bitmap> lurCache;
    private File cacheDir;
    private ExecutorService threadPool;

    // 设置图片放置图片大小,图片路径,构造方法中实现:
    public ImageCache(Context context) {
        // 设置图片的大小:
        int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);

        cacheDir = context.getCacheDir();

        // 存在集合中String:url
        lurCache = new LruCache<String, Bitmap>(maxSize) {

            // 重写sizeof的方法:计算每张图片的大小
            @Override
            protected int sizeOf(String key, Bitmap value) {
                int rowBytes = value.getRowBytes();
                int height = value.getHeight();
                return rowBytes * height;
            }

        };

        // 设置线程池中有几个线程
        threadPool = Executors.newFixedThreadPool(5);
    }

    // 设置图片到一个imageView上:
    public void display(String url, ImageView imageView) {
        // 1.先从集合中取
        Bitmap bitmap = getFromLruCache(url);
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
            return;
        }

        // 从手机存放的缓存文件夹中取
        bitmap = getFromCaheDir(url);
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
            return;
        }

        getFromNet(url, imageView);
        return;
    }

    private void getFromNet(String url, ImageView imageView) {
        // 从网络访问获取图片,需要开辟线程,从线程池中取一个线程进行:

        MyRunnable command = new MyRunnable(url, imageView);
        threadPool.execute(command);

    }

    public class MyRunnable implements Runnable {
        // 需要路径,所以需要将url传递过来
        public String url;
        public ImageView imageView;

        MyRunnable(String url, ImageView imageView) {
            this.url = url;
            this.imageView = imageView;
        }

        @Override
        public void run() {
            // 开始访问网络
            try {
                URL urlObj = new URL(url);
                HttpURLConnection conn = (HttpURLConnection) urlObj
                        .openConnection();
                conn.setConnectTimeout(5000);
                conn.setRequestMethod("GET");
                int responseCode = conn.getResponseCode();
                if (responseCode == 200) {
                    // 访问网络成功
                    InputStream in = conn.getInputStream();
                    // 解析Inputstream 中的数据
                    byte[] bs = StreamUtils.readInputStream(in);
                    Bitmap bitmap = BitmapFactory.decodeByteArray(bs, 0,
                            bs.length);
                    if (bitmap != null) {
                        // 通过handle将bitmap发送出去
                        Message message = new Message();
                        message.what = 200;
                        HashMap<String, Object> map = new HashMap<String, Object>();
                        map.put("imageView", imageView);// 为了防止图片错位的事情发生
                        map.put("bitmap", bitmap);
                        message.obj = map;
                        handler.sendMessage(message);

                        // 同时将bitmap保存到集合中
                        lurCache.put(url, bitmap);

                        // 保存到缓存文件中:
                        writeToCacheDir(url, bitmap);
                    }
                    return;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            // 如果走的是下面的代码:者说明网络访问是失败的:或为404,或为异常:
            Message message = new Message();
            message.what = 404;
            handler.sendMessage(message);
        }

    }

    // 处理消息:
    public Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 200) {
                HashMap<String, Object> map = (HashMap<String, Object>) msg.obj;
                ImageView imageView = (ImageView) map.get("imageView");
                Bitmap bitmap = (Bitmap) map.get("bitmap");
                imageView.setImageBitmap(bitmap);
            }

        };
    };

    private void writeToCacheDir(String url, Bitmap bitmap) {
        try {
            String fileName = URLEncoder.encode(url, "UTF-8");
            File imageFile = new File(cacheDir.getAbsolutePath() + "/"
                    + fileName);

            if (!imageFile.exists()) {
                imageFile.createNewFile();
            }

            // 用输出流往里面写数据:
            FileOutputStream fos = new FileOutputStream(imageFile);
            bitmap.compress(CompressFormat.JPEG, 80, fos);
            fos.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // 从缓存的文件夹中获取
    private Bitmap getFromCaheDir(String url) {
        // data/data/包名/cache/%%kjdjf%%kdfdl.jpg
        // 在存的时候将文件名编码了下,现在也将url也编译到文件名中去
        try {
            String fileName = URLEncoder.encode(url, "UTF-8");
            File imageFile = new File(cacheDir.getAbsolutePath() + "/"
                    + fileName);
            Bitmap bitmap = BitmapFactory.decodeFile(imageFile
                    .getAbsolutePath());

            // 保存到集合中:
            lurCache.put(url, bitmap);
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    private Bitmap getFromLruCache(String url) {
        Bitmap bitmap = lurCache.get(url);
        return bitmap;
    }
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值