編輯:關於Android編程
記得很久之前我寫了一篇banner的文章,好多朋友找我要代碼,並要我開放banner中使用的圖片管理工廠-ImageManager。如果想很好地理解下面的故事,請參看我半年前寫的兩篇博文:android中圖片的三級cache策略(內存、文件、網絡) 一和android中左右滑屏的實現(廣告位banner組件)。
當時沒有發上來是由於如下幾點原因:首先代碼較多,其次當時寫的時候也參考了網絡上存在的三級cache策略(大同小異),並且采用了Android項目中開源的LruCache頁面淘汰算法(近期最少使用算法),還有一點就是這是實際項目使用的代碼,不便直接開放,但是現在我決定把它稍作修改後開放給大家。這裡我想說說那個banner,平心而論,banner的代碼很多,如果采用ViewPager之類的則可以減少不少代碼,但是我更看重banner的實現思想以及它的封裝和事件傳遞,在自定義控件的封裝和架構上,我到現在還覺得banner是及其成功的,尤其是banner和ImageManager結合以後,整個功能渾然天成,超高內聚,使用起來及其方便,最少只需要兩行代碼,你不需要導入xml,也不需要處理Json拉取策略,因為相關業務層都被封裝在了banner內部,對外只保留很少的幾個接口,只要實現它就能和banner內部進行交互。下面我將要介紹三級cache策略之二:內存緩存策略。
當有一個圖片要去從網絡下載的時候,我們並不會直接去從網絡下載,因為在這個時代,用戶的流量是寶貴的,耗流量的應用是不會得到用戶的青睐的。那我們該怎麼辦呢?這樣,我們會先從內存緩存中去查找是否有該圖片,如果沒有就去文件緩存中查找是否有該圖片,如果還沒有,我們就從網絡下載圖片。本博文的側重點是如何做內存緩存。這裡,我有必要說明下幾個概念:強引用、軟引用、弱引用、Lru。
強引用:就是直接引用一個對象,一般的對象引用均是強引用
軟引用:引用一個對象,當內存不足並且除了我們的引用之外沒有其他地方引用此對象的情況 下,該對象會被gc回收
弱引用:引用一個對象,當除了我們的引用之外沒有其他地方引用此對象的情況下,只要gc被調用,它就會被回收(請注意它和軟引用的區別)
Lru:Least Recently Used 近期最少使用算法,是一種頁面置換算法,其思想是在緩存的頁面數目固定的情況下,那些最近使用次數最少的頁面將被移出,對於我們的內存緩存來說,強引用緩存大小固定為4M,如果當緩存的圖片大於4M的時候,有些圖片就會被從強引用緩存中刪除,哪些圖片會被刪除呢,就是那些近期使用次數最少的圖片。
public class ImageMemoryCache { /** * 從內存讀取數據速度是最快的,為了更大限度使用內存,這裡使用了兩層緩存。 * 強引用緩存不會輕易被回收,用來保存常用數據,不常用的轉入軟引用緩存。 */ private static final String TAG = "ImageMemoryCache"; private static LruCachemLruCache; // 強引用緩存 private static LinkedHashMap > mSoftCache; // 軟引用緩存 private static final int LRU_CACHE_SIZE = 4 * 1024 * 1024; // 強引用緩存容量:4MB private static final int SOFT_CACHE_NUM = 20; // 軟引用緩存個數 // 在這裡分別初始化強引用緩存和弱引用緩存 public ImageMemoryCache() { mLruCache = new LruCache (LRU_CACHE_SIZE) { @Override // sizeOf返回為單個hashmap value的大小 protected int sizeOf(String key, Bitmap value) { if (value != null) return value.getRowBytes() * value.getHeight(); else return 0; } @Override protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { if (oldValue != null) { // 強引用緩存容量滿的時候,會根據LRU算法把最近沒有被使用的圖片轉入此軟引用緩存 Logger.d(TAG, "LruCache is full,move to SoftRefernceCache"); mSoftCache.put(key, new SoftReference (oldValue)); } } }; mSoftCache = new LinkedHashMap >( SOFT_CACHE_NUM, 0.75f, true) { private static final long serialVersionUID = 1L; /** * 當軟引用數量大於20的時候,最舊的軟引用將會被從鏈式哈希表中移出 */ @Override protected boolean removeEldestEntry( Entry > eldest) { if (size() > SOFT_CACHE_NUM) { Logger.d(TAG, "should remove the eldest from SoftReference"); return true; } return false; } }; } /** * 從緩存中獲取圖片 */ public Bitmap getBitmapFromMemory(String url) { Bitmap bitmap; // 先從強引用緩存中獲取 synchronized (mLruCache) { bitmap = mLruCache.get(url); if (bitmap != null) { // 如果找到的話,把元素移到LinkedHashMap的最前面,從而保證在LRU算法中是最後被刪除 mLruCache.remove(url); mLruCache.put(url, bitmap); Logger.d(TAG, "get bmp from LruCache,url=" + url); return bitmap; } } // 如果強引用緩存中找不到,到軟引用緩存中找,找到後就把它從軟引用中移到強引用緩存中 synchronized (mSoftCache) { SoftReference bitmapReference = mSoftCache.get(url); if (bitmapReference != null) { bitmap = bitmapReference.get(); if (bitmap != null) { // 將圖片移回LruCache mLruCache.put(url, bitmap); mSoftCache.remove(url); Logger.d(TAG, "get bmp from SoftReferenceCache, url=" + url); return bitmap; } else { mSoftCache.remove(url); } } } return null; } /** * 添加圖片到緩存 */ public void addBitmapToMemory(String url, Bitmap bitmap) { if (bitmap != null) { synchronized (mLruCache) { mLruCache.put(url, bitmap); } } } public void clearCache() { mSoftCache.clear(); } }
IN THIS DOCUMENTCreating an Activity 創建一個ActivityImplementing a user interface 實現用戶界面
我們在上一節已經說了側滑菜單的實現原理,並且實現了單側菜單,這一節我們就完善項目,實現雙向側滑菜單。原理我們都說了,不明白的看上節,好了,直接上代碼/** * 這個類和S
這是一篇被逼出來的文章。一入SDK深似海,從此jar包是路人,沒錯,你以為我願意不用ViewPager和Fragment啊,因為SDK為了減少包體大小不能用v4的包啊!坑
版本:1.0日期:2014.5.16版權:© 2014 kince 轉載注明出處 這一次主要說一下Android下的進度條,為什麼是它呢,因為近期被其各種美輪