【構建Android緩存模塊】(二)Memory Cache & File Cache

聲明:Ryan的博客文章歡迎您的轉載,但在轉載的同時,請註明文章的來源出處,不勝感激! :-)  java

http://my.oschina.net/ryanhoo/blog/93406 android

    節課咱們講到普通應用緩存Bitmap的實現分析,根據MVC的實現原理,我將這個簡單的緩存實現單獨寫成一個模塊,這樣能夠方便之後的使用,對於任意的需求,都屬於一個可插拔式的功能。 緩存

    以前提到,這個緩存模塊主要有兩個子部件:
異步

    Memory Cache:內存緩存的存取速度很是驚人,遠遠快於文件讀取,若是沒有內存限制,固然首選這種方式。遺憾的是咱們有着16M的限制(固然大多數設備限制要高於Android官方說的這個數字),這也正是大Bitmap容易引發OOM的緣由。Memory Cache將使用WeakHashMap做爲緩存的中樞,當程序內存告急時,它會主動清理部分弱引用(所以,當引用指向爲null,咱們必須轉向硬盤緩存讀取數據,若是硬盤也沒有,那仍是從新下載吧)。 ide

    能力越大,責任越大?人家只是跑得快了點兒,總得讓人家休息,咱們必定不但願讓內存成爲第一位跑完馬拉松的Pheidippides,一次之後就掛了吧?做爲精打細算的猿媛,咱們只能將有限的內存分配給Memory Cache將更繁重的任務託付給不辭辛苦的SDCard
this

    File Cache:硬盤讀取速度固然不如內存,可是爲了珍惜寶貴的流量,不讓你的用戶在月底沒有流量時嚎叫着要刪掉你開發的「流量殺手」,最好是避免重複下載。在第一次下載之後,將數據保存在本地便可。 spa

    文件讀寫的技術並非很新穎的技術,Java Core那點兒就夠你用了。不過要記得咱們但是將Bitmap寫入文件啊,怎麼寫入呢?不用着急,Android的Bitmap自己就具有將數據寫入OutputStream的能力。我將這些額外的方法寫在一個幫助類中:BitmapHelper .net

public static boolean saveBitmap(File file, Bitmap bitmap){
	if(file == null || bitmap == null)
		return false;
	try {
		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
		return bitmap.compress(CompressFormat.JPEG, 100, out);
	} catch (FileNotFoundException e) {
		e.printStackTrace();
		return false;
	}
}
    最後附上Memory Cache和File Cache的具體代碼,很是簡單。


public class MemoryCache {
	private static final String TAG = "MemoryCache";
	
	//WeakReference Map: key=string, value=Bitmap
    private WeakHashMap<String, Bitmap> cache = new WeakHashMap<String, Bitmap>();
    
    /**
     * Search the memory cache by a unique key. 
     * @param key Should be unique. 
     * @return The Bitmap object in memory cache corresponding to specific key.
     * */
    public Bitmap get(String key){
        if(key != null)
        	return cache.get(key);
        return null;
    }
    
    /**
     * Put a bitmap into cache with a unique key.
     * @param key Should be unique.
     * @param value A bitmap.
     * */
    public void put(String key, Bitmap value){
    	if(key != null && !"".equals(key) && value != null){
    		cache.put(key, value);
    		//Log.i(TAG, "cache bitmap: " + key);
    		Log.d(TAG, "size of memory cache: " + cache.size());
    	}
    }

    /**
     * clear the memory cache.
     * */
    public void clear() {
        cache.clear();
    }
}
public class FileCache {
	
	private static final String TAG = "MemoryCache";
	
	private File cacheDir;	//the directory to save images

	/**
	 * Constructor
	 * @param context The context related to this cache.
	 * */
	public FileCache(Context context) {
		// Find the directory to save cached images
		if (android.os.Environment.getExternalStorageState()
				.equals(android.os.Environment.MEDIA_MOUNTED))
			cacheDir = new File(
					android.os.Environment.getExternalStorageDirectory(),
					Config.CACHE_DIR);
		else
			cacheDir = context.getCacheDir();
		if (!cacheDir.exists())
			cacheDir.mkdirs();
		
		Log.d(TAG, "cache dir: " + cacheDir.getAbsolutePath());
	}

	/**
	 * Search the specific image file with a unique key.
	 * @param key Should be unique.
	 * @return Returns the image file corresponding to the key.
	 * */
	public File getFile(String key) {
		File f = new File(cacheDir, key);
		if (f.exists()){
			Log.i(TAG, "the file you wanted exists " + f.getAbsolutePath());
			return f;
		}else{
			Log.w(TAG, "the file you wanted does not exists: " + f.getAbsolutePath());
		}

		return null;
	}

	/**
	 * Put a bitmap into cache with a unique key.
	 * @param key Should be unique.
	 * @param value A bitmap.
	 * */
	public void put(String key, Bitmap value){
		File f = new File(cacheDir, key);
		if(!f.exists())
			try {
				f.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		//Use the util's function to save the bitmap.
		if(BitmapHelper.saveBitmap(f, value))
			Log.d(TAG, "Save file to sdcard successfully!");
		else
			Log.w(TAG, "Save file to sdcard failed!");
		
	}
	
	/**
	 * Clear the cache directory on sdcard.
	 * */
	public void clear() {
		File[] files = cacheDir.listFiles();
		for (File f : files)
			f.delete();
	}
}
    沒什麼難的地方,直接貼代碼。下節課我講講解如何使用異步任務下載數據,以及使用Controller操做Model,控制View的顯示。
相關文章
相關標籤/搜索