当前位置:操作系统 > 安卓/Android >>

android中图片的三级cache策略(内存、文件、网络) 一

1. 简介

现在android应用中不可避免的要使用图片,有些图片是可以变化的,需要每次启动时从网络拉取,这种场景在有广告位的应用以及纯图片应用(比如百度美拍)中比较多。

现在有一个问题:假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响。当然,我想,向百度美拍这样的应用,必然也有其内部的图片缓存策略。总之,图片缓存是很重要而且是必须的。

 

2.图片缓存的原理

实现图片缓存也不难,需要有相应的cache策略。这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且也把它划到缓存的层次结构中。当根据url向网络拉取图片的时候,先从内存中找,如果内存中没有,再从缓存文件中查找,如果缓存文件中也没有,再从网络上通过http请求拉取图片。在键值对(key-value)中,这个图片缓存的key是图片url的hash值,value就是bitmap。所以,按照这个逻辑,只要一个url被下载过,其图片就被缓存起来了。

 


关于Java中对象的软引用(SoftReference),如果一个对象具有软引用,内存空间足够,垃 圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高 速缓存。使用软引用能防止内存泄露,增强程序的健壮性。 

 


从代码上来说,采用一个ImageManager来负责图片的管理和缓存,函数接口为public void loadBitmap(String url, Handler handler) ;其中url为要下载的图片地址,handler为图片下载成功后的回调,在handler中处理message,而message中包含了图片的信息以及bitmap对象。ImageManager中使用的ImageMemoryCache(内存缓存)、ImageFileCache(文件缓存)以及LruCache(最近最久未使用缓存)会在后续文章中介绍。

 


3.代码ImageManager.java

 

[java]  /*
 * 图片管理
 * 异步获取图片,直接调用loadImage()函数,该函数自己判断是从缓存还是网络加载
 * 同步获取图片,直接调用getBitmap()函数,该函数自己判断是从缓存还是网络加载
 * 仅从本地获取图片,调用getBitmapFromNative()
 * 仅从网络加载图片,调用getBitmapFromHttp()
 * 
 */ 
 
public class ImageManager implements IManager 

    private final static String TAG = "ImageManager"; 
     
    private ImageMemoryCache imageMemoryCache; //内存缓存  
     
    private ImageFileCache   imageFileCache; //文件缓存  
     
    //正在下载的image列表  
    public static HashMap<String, Handler> ongoingTaskMap = new HashMap<String, Handler>(); 
     
    //等待下载的image列表  
    public static HashMap<String, Handler> waitingTaskMap = new HashMap<String, Handler>(); 
     
    //同时下载图片的线程个数  
    final static int MAX_DOWNLOAD_IMAGE_THREAD = 4; 
     
    private final Handler downloadStatusHandler = new Handler(){ 
        public void handleMessage(Message msg) 
        { 
            startDownloadNext(); 
        } 
    }; 
     
    public ImageManager() 
    { 
        imageMemoryCache = new ImageMemoryCache(); 
        imageFileCache = new ImageFileCache(); 
    } 
     
    /**
     * 获取图片,多线程的入口
     */ 
    public void loadBitmap(String url, Handler handler)  
    { 
        //先从内存缓存中获取,取到直接加载  
        Bitmap bitmap = getBitmapFromNative(url); 
         
        if (bitmap != null) 
        { 
            Logger.d(TAG, "loadBitmap:loaded from native"); 
            Message msg = Message.obtain(); 
            Bundle bundle = new Bundle(); 
            bundle.putString("url", url); 
            msg.obj = bitmap; 
            msg.setData(bundle); 
            handler.sendMessage(msg); 
        }  
        else 
        { 
            Logger.d(TAG, "loadBitmap:will load by network"); 
            downloadBmpOnNewThread(url, handler); 
        } 
    } 
     
    /**
     * 新起线程下载图片
     */ 
    private void downloadBmpOnNewThread(final String url, final Handler handler) 
    { 
        Logger.d(TAG, "ongoingTaskMap'size=" + ongoingTaskMap.size()); 
         
        if (ongoingTaskMap.size() >= MAX_DOWNLOAD_IMAGE_THREAD)  
        { 
            synchronized (waitingTaskMap)  
            { 
                waitingTaskMap.put(url, handler); 
            } 
        }  
        else  
        { 
            synchronized (ongoingTaskMap)  
            { 
                ongoingTaskMap.put(url, handler); 
            } 
 
            new Thread()  
            { 
                public void run() &nbs

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,