Android--简单的图片三级缓存工具类

ImageUtils.java
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.LruCache;

import org.xutils.common.util.MD5;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 三级缓存的图片加载工具类
 */
public class ImageUtils {

    public static final String CACHE_IMAGE_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/image_cache/";
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);

    private static LruCache<String, Bitmap> lruCache;

    static {
        // 设置最大缓存空间为运行时内存的1/10
        int maxCacheMemory = (int) (Runtime.getRuntime().maxMemory() / 8);
        lruCache = new LruCache<String, Bitmap>(maxCacheMemory) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                // 计算一个元素的缓存大小
                return value.getByteCount();
            }
        };

        File file = new File(CACHE_IMAGE_DIR);
        if(!file.exists()) {
            file.mkdirs();
        }
    }

    private static void putCache(String key, Bitmap bm) {
        lruCache.put(key, bm);
    }

    private static Bitmap getCache(String key) {
        return lruCache.get(key);
    }

    public static void load(String url, OnBitmapCallback callback) {
        if (callback == null) {
            return;
        }

        Bitmap bitmap = null;
        String pathName = CACHE_IMAGE_DIR + generateCacheName(url);
        // 1.从内存获取
        bitmap = getCache(pathName);
        if (bitmap != null) {
            callback.onSuccess(bitmap);
            System.out.println("从内存拿~~~~~~~~~~~" + url);
            return;
        }

        // 2.从本地存储获取
        bitmap = getBitmapFromDisk(pathName);
        if (bitmap != null) {
            // 缓存到内存
            putCache(pathName, bitmap);
            callback.onSuccess(bitmap);
            System.out.println("从本地磁盘拿~~~~~~~~~~~" + url);
            return;
        }

        // 3.从网络下载
        getBitmapFromRemote(url, callback);
    }

    public static void getBitmapFromRemote(final String url, final OnBitmapCallback callback) {
        if (callback == null) {
            return;
        }

        executor.submit(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = null;
                HttpURLConnection conn = null;
                InputStream inputStream = null;
                FileOutputStream fos = null;
                try {
                    URL uri = new URL(url);
                    conn = (HttpURLConnection) uri.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(3000);
                    conn.setReadTimeout(5000);
                    inputStream = conn.getInputStream();
                    if (conn.getResponseCode() == 200) {
                        bitmap = BitmapFactory.decodeStream(inputStream);
                    }

                    if (bitmap != null) {
                        String pathName = CACHE_IMAGE_DIR + generateCacheName(url);
                        fos = new FileOutputStream(pathName);
                        // 先写入到本地文件,再重新读取decode成Bitmap,能否一次操作两步?
                        // compress()方法保存好图片后,需要重新构造才能使用!!
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
                        fos.close();

                        bitmap = getBitmapFromDisk(pathName);
                        putCache(pathName, bitmap);
                        callback.onSuccess(bitmap);
                    } else { // 最后如果从网络也获取不到那么就回调错误方法
                        callback.onFail(404);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (inputStream != null) {
                            inputStream.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }


                    if (conn != null) {
                        conn.disconnect();
                    }
                }
            }
        });
    }

    public static Bitmap getBitmapFromDisk(String pathName) {
        return BitmapFactory.decodeFile(pathName);
    }

    public static String generateCacheName(String str) {
        return MD5.md5(str);
    }

    public static void clearCache() {
        // 清除内存缓存
        lruCache.evictAll();
        // 清除磁盘缓存
        File path = new File(CACHE_IMAGE_DIR);
        if (path.exists()) {
            if (path.isDirectory()) {
                for (File f : path.listFiles()) {
                    f.deleteOnExit();
                }
            } else {
                path.delete();
            }
        }
    }

    public static interface OnBitmapCallback {
        void onSuccess(Bitmap bm);

        void onFail(int errorCode);
    }
}

定义了一个使用上面的工具来绑定ImageView的工具类:ImageBinder.java

import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView;

public class ImageBinder {

    public static void bind(final ImageView view, String url) {
        // Handler使用了主线程的Looper,所以发送的消息也是在主线程里被处理
        final Handler handler = new Handler(Looper.getMainLooper());

        ImageUtils.load(url, new ImageUtils.OnBitmapCallback() {
            @Override
            public void onSuccess(final Bitmap bm) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        view.setImageBitmap(bm);
                    }
                });
            }

            @Override
            public void onFail(int errorCode) {
            }
        });
    }

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值