(MyStudy:一)三级缓存:首先是内存-文件(外存)-网络三级缓存机制。

来源:互联网 发布:hadoop windows版本 编辑:程序博客网 时间:2024/04/19 03:10

三级缓存:首先是内存-文件(外存)-网络三级缓存机制。
三级缓存
首先:
框架需要一个接入方法NGImageloadHelper.Java:

/** * 图片加载框架使用帮助类 * Created by nangua on 2016/7/8. */public class NGImageloadHelper {    /**     * 处理图片     * @param view     * @param url     */    public static void displayImage(ImageView view,                                    String url) {        NGDownloadImage.getInstance().addTask(url,                view);        NGDownloadImage.getInstance().doTask();    }}

然后,使用具体的缓存实现类NGDownloadImage:
首先判断传入的url对应图片是否在内外存中,如果不在,则添加进线程池的自定义任务队列中,这里传入的任务是自定义的实现Callble接口的任务TaskWithResult,在带回调参数的执行方法call中执行一个自定义的handler—-TaskHandler,该TaskHandler的handlerMessage方法内部根据传入的图片类型判断,执行相应的下载方法(通过HttpUrlConnection实现)并移除taskmap中对应的图片任务。

/** * 图片加载类 * Created by nangua on 2016/7/8. */public class NGDownloadImage {    private ExecutorService executorService; //线程池服务    private NGImageMemoryCache imageMemoryCache;    private NGImageFileCache imageFileCache;    private NGDownloadImageMode downloadImageMode; //图片实例    private Map<String, View> taskMap;    private static NGDownloadImage instance; //自身私有化实例    private int POOL_SIZE = 5;//线程池自定义大小    private NGDownloadImage() {        final int cpuNums = Runtime.getRuntime().availableProcessors();//cpu数        executorService = Executors.newFixedThreadPool(cpuNums * POOL_SIZE);        imageMemoryCache = new NGImageMemoryCache();        imageFileCache = new NGImageFileCache();        downloadImageMode = new NGDownloadImageMode();        taskMap = new HashMap<>();    }    //获得唯一实例    public static synchronized NGDownloadImage getInstance() {        if (instance == null) {            instance = new NGDownloadImage();        }        return instance;    }    /**     * 添加任务     *     * @param url     * @param img     */    public void addTask(String url, ImageView img) {        addTask(null, url, img, null);    }    public void addTask(Object parent, String url, View img,                        NGImageCallback callback) {        if (img == null) {            return;        }        if (TextUtils.isEmpty(url)) {            return;        }        if (callback != null) {            downloadImageMode = new NGDownloadImageMode();            downloadImageMode.setCallback(callback);            downloadImageMode.setParent(parent);            downloadImageMode.setImgUrl(url);            img.setTag(downloadImageMode);        } else {            img.setTag(url);        }        //生成Bitmap        final Bitmap bitmap = imageMemoryCache.getBitmapFromCache(url);        //如果缓存里有        if (bitmap != null) {            //如果有实现的回调接口,则用回调接口加载图片            if (callback != null) {                callback.imageLoaded(parent, img, bitmap, downloadImageMode);            } else {                //如果没有,则直接设置该图片为bitmap                if (img instanceof ImageView)                    ((ImageView) img).setImageBitmap(bitmap);            }        } else {            //如果缓存没有这个图片            if (taskMap != null) {                //添加到任务集合里去                synchronized (taskMap) {                    final String mapKey = Integer.toString(img.hashCode());                    if (!taskMap.containsKey(mapKey)) {                        taskMap.put(mapKey, img);                    }                }            }        }    }    public void doTask() {        if (taskMap == null) {            return;        } else {            synchronized (taskMap) {                Collection<View> collection = taskMap.values();                for (View view : collection) {                    if (view != null) {                        Object object = view.getTag();                        String url = "";                        if (object instanceof NGDownloadImageMode) {                            url = ((NGDownloadImageMode) object).getImgUrl();                        } else {                            url = (String) object;                        }                        if (!TextUtils.isEmpty(url)) {                            loadImage(url, view);                        }                    }                }            }        }    }    private void loadImage(final String url, final View img) {        loadImage(url, img, null);    }    private void loadImage(final String url, final View img,                           NGImageCallback callback) {        executorService.submit(new TaskWithResult(new TaskHandler(url, img,                callback), url));    }    private class TaskWithResult implements Callable<String> {        private String url;        private Handler handler;        public TaskWithResult(Handler handler, String url) {            this.url = url;            this.handler = handler;        }        @Override        public String call() throws Exception {            // TODO Auto-generated method stub            final Message message = handler.obtainMessage(0, getBitmap(url));            handler.sendMessage(message);            return url;        }    }    private class TaskHandler extends Handler {        private String url;        private View img;        private NGImageCallback callback;        public TaskHandler(String url, View img, NGImageCallback callback) {            this.url = url;            this.img = img;            this.callback = callback;        }        @Override        public void handleMessage(Message msg) {            final Object object = img.getTag();            if (object instanceof NGDownloadImageMode) {                final NGDownloadImageMode imageMode = (NGDownloadImageMode) object;                imageMode.getCallback().imageLoaded(imageMode.getParent(), img,                        (Bitmap) msg.obj, imageMode);                if (taskMap != null) {                    taskMap.remove(Integer.toString(img.hashCode()));                }            } else if (object instanceof String) {                if (callback != null) {                    callback.imageLoaded(null, img, (Bitmap) msg.obj, url);                } else {                    if (object.equals(url) && msg.obj != null) {                        final Bitmap bitmap = (Bitmap) msg.obj;                        if (bitmap != null) {                            if (img instanceof ImageView) {                                ((ImageView) img).setImageBitmap(bitmap);                            }                        }                    }                }                if (taskMap != null) {                    taskMap.remove(Integer.toString(img.hashCode()));                }            }        }    }    /**     * @param url     * @return Bitmap     */    public Bitmap getBitmap(String url) {        Bitmap bitmap = imageMemoryCache.getBitmapFromCache(url);        if (bitmap == null) {            bitmap = imageFileCache.getImage(url);            if (bitmap == null) {                bitmap = getBitmapFromUrl(url);                if (bitmap != null) {                    imageMemoryCache.addBitmapToCache(url, bitmap);                    imageFileCache.saveBmpToSd(url,bitmap);                }            } else {                imageMemoryCache.addBitmapToCache(url, bitmap);            }        }        return bitmap;    }    public static Bitmap getBitmapFromUrl(String path) {        try {            URL url = new URL(path);            HttpURLConnection conn = (HttpURLConnection) url.openConnection();            conn.setConnectTimeout(5000);            conn.setRequestMethod("GET");            if (conn.getResponseCode() == 200) {                InputStream inputStream = conn.getInputStream();                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);                return bitmap;            }        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    public interface NGImageCallback {        public void imageLoaded(Object parent, View img, Bitmap imageBitmap,                                NGDownloadImageMode callBackTag);        public void imageLoaded(Object parent, View img, Bitmap imageBitmap,                                String imageUrl);    }}

内存缓存实现:
通过强&软引用配合使用实现内存缓存机制,强引用使用HashMap实现,软引用使用线程安全的 ConcurrentHashMap实现(实现原理是锁分离技术,使用多个锁来控制对hash表的不同部分的修改,内部使用段(Segment)来表示这些不同的部分,每个段是一个小的hashtable,可并发运行),淘汰算法如下:

    /**     * 初始化     * 淘汰最老的键     */    protected NGImageMemoryCache() {        //使用LinkedHashMap保证有序读取        hashMap = new LinkedHashMap<String, Bitmap>(MAX_CACHE_CAPACITY, 0.75f, true) {            //移除hashmap中最老的键值            @Override            protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {                if (size() > MAX_CACHE_CAPACITY) {                    mSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));                    return true; //返回true则移除最老的键值                } else {                    return false;                }            }        };    }

外存缓存实现:
很简单这里就只讲一下思路了,把图片文件存储到本地指定文件夹中,注意进行剩余容量判断及时清除最老的图片就行了。

1 0
原创粉丝点击