Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 圖片SD卡緩存 使用簡單 支持預取 支持多種緩存算法 支持不同網絡類型 支持序列化 (八)

Android 圖片SD卡緩存 使用簡單 支持預取 支持多種緩存算法 支持不同網絡類型 支持序列化 (八)

編輯:關於Android編程

本文主要介紹一個支持圖片自動預取、支持多種緩存算法、支持數據保存和恢復的圖片Sd卡緩存的使用、功能及網友反饋的常見問題解答。

與AndroidLruCache相比主要特性:(1). 使用簡單 (2).輕松獲取及預取新圖片 (3).可選擇多種緩存算法(FIFO、LIFO、LRU、MRU、LFU、MFU等13種)或自定義緩存算法(4).可方便的保存及初始化恢復數據(5). 支持文件sd卡保存及自定義文件名規則(6). 省流量性能佳(有且僅有一個線程獲取圖片)(7).支持不同類型網絡處理(8).可根據系統配置初始化緩存(9).擴展性強(10).支持等待隊列(11).包含map的大多數接口。

 

適用:獲取圖片較多且圖片較大的應用,如新浪微博大圖、twitter大圖、微信圖片、美麗說、蘑菇街、花瓣、淘寶等等。

本文以用ImageSDCardCache實現Gallery為例,示例代碼地址見ImageSDCardCacheDemo,效果圖如下:

\

1、使用

(1)引入公共庫

引入TrineaAndroidCommon@Github(歡迎star和fork^_^)作為你項目的library,或是自己抽取其中的ImageSDCardCache.java部分使用。

(2)調用

僅需簡單三步:

a. AndroidManifest.xml中添加權限

b.定義緩存和回調接口

基本使用:只對ImageView加載圖片有效,定義只需要一條語句

 

public static final ImageSDCardCache IMAGE_SD_CACHE = CacheManager.getImageSDCardCache();
高級使用:自定義圖片獲取成功的回調接口,如下:
/** init cache **/
public static final ImageSDCardCache IMAGE_SD_CACHE = new ImageSDCardCache();
 
static {
    OnImageSDCallbackListener imageCallBack = new OnImageSDCallbackListener() {
 
		private static final long serialVersionUID = 1L;
 
		// callback function before get image, run on ui thread
		@Override
		public void onPreGet(String imageUrl, View view) {
			// Log.e(TAG_CACHE, "pre get image");
		}
 
		// callback function after get image successfully, run on ui thread
		@Override
		public void onGetSuccess(String imageUrl, String imagePath, View view, boolean isInCache) {
			ImageView imageView = (ImageView)view;
			Bitmap bm = BitmapFactory.decodeFile(imagePath);
			if (bm != null) {
				imageView.setImageBitmap(bm);
			}
		}
 
		// callback function after get image failed, run on ui thread
		@Override
		public void onGetFailed(String imageUrl, String imagePath, View view, FailedReason failedReason) {
			Log.e(TAG_CACHE,
				  new StringBuilder(128).append("get image ").append(imageUrl).append(" error"));
		}
	};
    IMAGE_SD_CACHE.setOnImageSDCallbackListener(imageCallBack);
    IMAGE_SD_CACHE.setCacheFolder(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "TrineaAndroidCommon");
}

 

 

c.需要加載圖片的地方調用get(String imageUrl, View view)異步加載圖片

 

IMAGE_SD_CACHE.get(imageUrl, imageView);

 

上面代碼中new ImageSDCardCache()用來定義圖片緩存,默認會根據系統內存設置緩存大小。默認緩存算法為LFU(Least Frequently Used),最近最少使用先刪除。

 

setOnImageSDCallbackListener(imageCallBack);設置圖片獲取成功回調接口,其中onPreGet為圖片獲取前的回調函數,onGetSuccess為圖片獲取成功的回調函數,onGetFailed為圖片獲取失敗的回調函數。

 

setCacheFolder(String cacheFolder)設置圖片文件保存路徑,默認為ImageSDCardCache#DEFAULT_CACHE_FOLDER

setFileNameRule(FileNameRule fileNameRule)設置圖片保存時文件名規則,默認根據url命名,見2.4部分詳細介紹

 

可以在程序退出時調用saveDataToDb(Context context, String tag)保存數據,在程序啟動時調用initData(Context context, String tag)初始化恢復數據。其中tag為此ImageCache的標識。

 

get(imageUrl, imageView)異步獲取圖片,在圖片獲取成功後會自動調用onImageLoaded將參數傳入。
get(String imageUrl,List urlList, View view)異步獲取圖片,並且會自動預取urlList中的圖片。

 

上面是最簡單的實現。
第2部分會介紹支持的其他功能,包括網絡類型設置、預取個數設置、多種緩存算法、圖片SD卡保存目錄及文件名規則設置、保存及初始化恢復數據、等待隊列開關、圖片源讀取方式設置、讀取圖片http設置、緩存有效時間、命中率及大部分map接口。

 

2、功能介紹
(1) 多種構造函數,可根據系統配置初始化緩存

public ImageSDCardCache()
public ImageSDCardCache(int maxSize)
public ImageSDCardCache(int maxSize, int threadPoolSize)
支持三種構造函數,支持緩存大小和獲取圖片線程池大小的設置。默認會根據系統可用內存大小設置緩存大小,根據系統Cpu個數設置線程池大小。

 

(2)、獲取圖片及自動預取
get(String imageUrl, View view)異步獲取圖片,在圖片獲取成功後自動調用OnImageSDCallbackListener的onImageLoaded函數,返回是否已在緩存中
get(String imageUrl, List urlList, View view)異步獲取圖片,在圖片獲取成功後自動調用OnImageSDCallbackListener的onImageLoaded函數,並且根據imageUrl在urlList中的位置向前向後預取圖片,返回是否已在緩存中。

 

public void setForwardCacheNumber(int forwardCacheNumber)向前預取圖片個數設置,默認為PreloadDataCache#DEFAULT_FORWARD_CACHE_NUMBER

public void setBackwardCacheNumber(int backwardCacheNumber)向後預取圖片個數設置默認,默認為PreloadDataCache#DEFAULT_BACKWARD_CACHE_NUMBER

 

public CacheObject get(K key)
public CacheObject get(K key, List keyList)
兩個接口是直接同步獲取圖片,且獲取成功後不會調用OnImageSDCallbackListener的onImageLoaded函數

 

(3)、設置緩存算法
setCacheFullRemoveType(CacheFullRemoveType cacheFullRemoveType)
設置緩存算法,緩存算法即為緩存滿時為了插入新數據,刪除舊數據的規則。

 

目前包括FIFO、LIFO、LRU、MRU、LFU、MFU、優先級低先刪除、優先級高先刪除、數據小先刪除、數據大先刪除、圖片小先刪除、圖片大先刪除、永不刪除。還可以通過實現CacheFullRemoveType來自定義緩存算法。。默認為RemoveTypeUsedCountSmall,即LRU使用頻率低先刪除。下面詳細介紹各個算法:

RemoveTypeEnterTimeFirst FIFO先進先出,先進入先刪除
RemoveTypeEnterTimeLast LIFO後進先出,後進入先刪除
RemoveTypeLastUsedTimeFirst LRU(Least Recently User),最先使用先刪除
RemoveTypeLastUsedTimeLast MRU(Most Recently Used),最近使用先刪除
RemoveTypeUsedCountSmallLFU(Least Frequently Used),使用頻率低先刪除
RemoveTypeUsedCountBig MRU(Most Frequently Used),使用頻率高先刪除
RemoveTypePriorityLow 優先級低先刪除
RemoveTypePriorityHigh 優先級低先刪除
RemoveTypeFileSmall 文件小的先刪除
RemoveTypeFileLarge 文件大的先刪除

RemoveTypeDataBig 數據大先刪除,根據緩存數據的compareTo函數決定
RemoveTypeDataSmall 數據小先刪除,根據緩存數據的compareTo函數決定
RemoveTypeNotRemove 不刪除,緩存滿時不再允許插入新數據

 

自定義緩存算法只需要實現CacheFullRemoveType的compare方法即可。比較結果小於0表示會被先刪除

public class MyRemoveType implements CacheFullRemoveType {
 
    private static final long serialVersionUID = 1L;
 
    @Override
    public int compare(CacheObject obj1, CacheObject obj2) {
        // process and return, smaller than zero means may be removed
        return ***;
    }
}

(4)、設置圖片SD卡保存目錄及文件名規則

setCacheFolder(String cacheFolder)設置圖片文件保存路徑,默認為ImageSDCardCache#DEFAULT_CACHE_FOLDER

setFileNameRule(FileNameRule fileNameRule)設置圖片保存時文件名規則,默認根據url命名。已有命名規則有:

FileNameRuleImageUrl 根據圖片url命名,url中所有非數字字母都會替換為_

FileNameRuleCurrentTime 根據當前圖片獲取成功時間命名,支持各種時間格式,見FileNameRuleCurrentTime#TimeRule

 

自定義文件命名規則算法只需要實現FileNameRule的getFileName方法即可。返回結果即為文件名,注釋不能包含文件名以外的非法字符

 

public class MyFileNameRule implements FileNameRule {
 
    private static final long  serialVersionUID     = 1L;
 
    @Override
    public String getFileName(String imageUrl) {
        // process and return, the result need not contain char which not allowed in File name
        return ****;
    }

 

(5)、保存及初始化恢復數據
public booleansaveDataToDb(Context context, String tag)
保存數據到數據庫,可在程序退出時調用,不建議在activity onDestrory時調用,而是整個程序退出時,見本文3.1常見問題解答。

public voidinitData(Context context, String tag)

初始化恢復數據,可在程序剛開始加載時調用,不建議在每個activity oncreate調用,而是整個程序初始化時,見本文3.1常見問題解答。

 

(6)、是否啟用隊列

setOpenWaitingQueue(boolean isOpenWaitingQueue)
當不同view通過get函數獲取圖片時,是否開啟等待隊列。

若開啟,保存所有view,圖片獲取成功後依次調用OnImageSDCallbackListener的onImageLoaded函數;否則僅保存最後調用get的view,圖片獲取成功後調用OnImageSDCallbackListener的onImageLoaded函數
默認開啟隊列等待。如果希望最優性能且場景滿足,可設置為false。

 

(7)、設置圖片獲取方式接口
setOnGetDataListener(OnGetDataListener onGetDataListener)
設置圖片獲取的方式。緩存通過該接口獲取圖片及預取圖片。默認為ImageSDCardCache中getDefaultOnGetImageListener,通過url獲取圖片。你可以重寫該方法將圖片緩存改為本地圖片文件緩存等等。

 

(8)、讀取圖片http設置
a. 設置圖片讀取http超時
public voidsetHttpReadTimeOut(int readTimeOutMillis)
若readTimeOutMillis小於0表示不設置超時,默認不設置,單位為毫秒

b. 設置無網絡不讀取
public void setContext(Context context)
設置context,網絡連接失敗不會新建線程請求圖片。

c. 支持不同網絡類型的處理
public void setAllowedNetworkTypes(int allowedNetworkTypes)
設置允許的網絡類型,可選擇PreloadDataCache#NETWORK_MOBILE、PreloadDataCache#NETWORK_WIFI或兩者都允許。默認兩者都允許。
注意:這個接口生效必須先setContext(Context context)

d. 設置讀取圖片http請求屬性
public voidsetRequestProperties(Map requestProperties)

public voidsetRequestProperty(String field, String newValue)
設置獲取圖片時的http request屬性,如

setRequestProperty(“User-Agent”, “TrineaAndroidCommon/4.0 (Android 4.0) MI_2S”);設置User-Agent頭信息
setRequestProperty(“Connection”, “false”);設置connection keep alive為false,默認為true

(9)、緩存元素有效時間
setValidTime(long validTime)
設置緩存元素有效時間,小於0表示不會失效,此時僅根據CacheFullRemoveType在緩存滿時替換元素
通過protected boolean isExpired(K key)判斷某key是否過期

(10)、緩存命中率
getHitRate()、getHitCount()、getMissCount()分別表示緩存命中率、命中次數、未命中次數

(11)、其他與map類似接口
public boolean containsKey(K key) 緩存中是否包含該key
public CacheObject remove(K key) 從緩存中刪除某個key
public void clear() 清空緩存
public Set keySet() 緩存中key集合
public Set>> entrySet() 緩存中key,value鍵值對集合
public Collection> values() 緩存中元素集合
public CacheObject put(K key, V value) 手動插入某個元素
public CacheObject put(K key, CacheObject value) 手動插入某個元素
public CacheObject get(K key) 得到某個key
public int getSize() 得到緩存中有效元素個數
public int getMaxSize() 得到緩存中元素最大個數

(12)得到設置
上面的set幾乎都可以通過對應的get得到相應value
使用getOnGetDataListener()得到獲取圖片的方法
getForwardCacheNumber()得到自動向前緩存的個數
getBackCacheNumber()得到自動向後緩存的個數
getMaxSize()得到緩存最大容量
getValidTime()得到有效時間,以毫秒計
getCacheFullRemoveType()得到cache滿時刪除元素類型

3、常見問題解答
1、是每個Activity一個ImageSDCardCache還是整個程序共用一個?

建議ImageSDCardCache緩存整個app用同一個實例,而不是每個activity一個。在程序啟動時initData初始化圖片緩存,退出saveDataToDb保存圖片緩存。因為:
a. 你的程序總不能就一個activity需要圖片緩存,緩存本身就該應該所有頁面共用
b. 每次進activity新建一個緩存只會增加系統消耗,沒有必要
c. 這個緩存不會占用太多內存,所以程序運行期間一直存在也不會對性能有多大影響

2、為什麼應用退出後會重新獲取圖片?為什麼應用退出後無網絡情況下之前緩存的圖片不會自己加載?

在程序退出(比如onDestroy函數)時調用saveDataToDb(Context context, String tag)保存數據,在程序啟動(比如onCreate函數)時調用initData(Context context, String tag)初始化數據。其中tag為此ImageCache的標識。

3、為什麼無法加載圖片?
可通過OnImageSDCallbackListener中的onGetFailed函數FailedReason參數判斷失敗原因。目前錯誤原因包括sdcard保存出錯(請確保存在外部sdcard)和網絡出錯。

4、能否直接加載sdcard中已經存在的圖片,即數據源為本地sdcard而不是網絡?
可以通過setOnGetDataListener(OnGetDataListener onGetDataListener)設置圖片獲取方式

5、配合ListView和GridView使用時卡頓?
請使用ImageCache,包含二級緩存,性能更佳

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved