Android-Universal-Image-Loader學習筆記(一)

來源:互聯網
上載者:User

Android-Universal-Image-Loader是一個開源項目,負責處理圖片的載入和緩衝。閑暇之時看了一些原始碼,特記錄之。

說道圖片檔案(磁碟)緩衝,需要考慮如下的因素

1) 快取檔案的名稱的定義

2) 緩衝的大小

3) 快取檔案的方式:比如限時儲存檔案等,圖片壓縮後的格式,壓縮率等等。

該項目對磁碟緩衝儲存檔案時對檔案名稱的修改也做了支援:在快取檔案時對檔案名稱的修改提供了兩種方式,每一種方式對應了一個Java類

1) HashCodeFileNameGenerator,該類負責擷取檔案名稱的hashcode然後轉換成字串。

2) Md5FileNameGenerator,該類把源檔案的名稱同過md5加密後儲存。兩個類都繼承了FileNameGenerator介面

它們之間的關係如所示

<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHAgYWxpZ249"left">在DefaultConfigurationFactory類中提供了一個Factory 方法createFileNameGenerator,該方法返回了一個預設的FileNameGenerator對象:HashCodeFileNameGenerator.

public static FileNameGenerator createFileNameGenerator() {return new HashCodeFileNameGenerator();}

下面說說磁碟緩衝的具體實現:

首先定義了DiscCacheAware介面,該介面提供了如下方法

方法名

說明

返回值

getFileDectory()

返回磁碟緩衝的根目錄

File

get(String imageUri)

根據uri從緩衝中擷取圖片

File

save(imageUri,InputStream iamgeStream,IoUtils.CopyListener listener)

把圖片儲存在磁碟緩衝上

boolean

save(imageUri,Bitmap bitmap)

儲存bitMap對象到磁碟緩衝上

Boolean

remove(imageUri)

根據imageUri刪除檔案

boolean

close()

關閉磁碟緩衝,釋放資源

void

clear()

清空磁碟緩衝

void

然後定義了另外一個沒方法的介面DiskCache(這個介面名稱應該命名為DiscCache比較好),該介面只是簡單的繼承了DiscCacheAware介面

BaseDiscCache實現了DiskCache,該類是個抽象類別(定義為抽象類別的好處之一就是沒必要全部重寫DiskCacheAware介面提供的方法),該類定義了磁碟緩衝區的以下的(預設)屬性:

1) 預設的緩衝大小為32k

2) 預設壓縮後的圖片格式為PNG(作為Bitmap的compress方法的第一個參數)

3) 預設壓縮後圖片顯示的品質為100,也就是壓縮率為0,不進行壓縮(作為compress的第二個參數)

當然該類也提供了修改壓縮圖片格式和壓縮率以及修改緩衝大小的set方法。同時該類還封裝了以下三個屬性

protected final File cacheDir;//快取檔案的儲存Directoryprotected final File reserveCacheDir;//後備緩衝的Diectory,當cacheDir不存在的情況下就是用reserveCahceDir後備緩衝protected final FileNameGenerator fileNameGenerator;//檔案名稱名稱產生器

該類提供了三個建構函式

1) 只有一個參數的建構函式只初始化了cacheDir,沒有用到後備緩衝,且是以HashCodeFileNameGenerator來產生目標檔案的檔案名稱。

2) 兩個參數的構造器除了cacheDir和HashCodefileNameGenerator外,也可以初始化後備緩衝

3) 三個參數的構造器要求必須初始化cacheDir並且必須初始化filenNameGenerator否則就報異常

三個構造器的代碼如下

public BaseDiscCache(File cacheDir) {this(cacheDir, null);}public BaseDiscCache(File cacheDir, File reserveCacheDir) {this(cacheDir, reserveCacheDir, DefaultConfigurationFactory.createFileNameGenerator());}public BaseDiscCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator) {if (cacheDir == null) {throw new IllegalArgumentException("cacheDir" + ERROR_ARG_NULL);}if (fileNameGenerator == null) {throw new IllegalArgumentException("fileNameGenerator" + ERROR_ARG_NULL);}this.cacheDir = cacheDir;this.reserveCacheDir = reserveCacheDir;this.fileNameGenerator = fileNameGenerator;}

BasicDiscCache實現了除close之外的其餘的六個方法,下面進行一一說明:

1) clear():迴圈便利cacheDir.listFiles()的每一個File對象,然後調用File對象的delete()方法來清空緩衝

2) getDirectory():直接返回了cacheDir

3) get(StringimageUri):該方法調用BasicCahce的一個重要方法getFile(String imageUri).

該方法如下所示(該方法在save方法中也有調用)

protected File getFile(String imageUri) {String fileName = fileNameGenerator.generate(imageUri);File dir = cacheDir;if (!cacheDir.exists() && !cacheDir.mkdirs()) {if (reserveCacheDir != null && (reserveCacheDir.exists() || reserveCacheDir.mkdirs())) {dir = reserveCacheDir;}}return new File(dir, fileName);}

4) save(StringimageUri, Bitmap bitmap)方法的具體實現

public boolean save(String imageUri, Bitmap bitmap) throws IOException {//擷取imageUri的File對象,該對象封裝了緩衝路徑和圖片儲存後的名稱File imageFile = getFile(imageUri);//擷取臨時儲存檔案的tmpFile對象File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX);OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize);boolean savedSuccessfully = false;try {//調用compress把bitMap壓縮到tempFile中savedSuccessfully = bitmap.compress(compressFormat, compressQuality, os);} finally {IoUtils.closeSilently(os);//如果儲存成功並且tempFile的檔案沒有成功移動到imageFile的話,就刪除temFileif (savedSuccessfully && !tmpFile.renameTo(imageFile)) {savedSuccessfully = false;}if (!savedSuccessfully) {tmpFile.delete();}}//對bitmap進行記憶體回收bitmap.recycle();return savedSuccessfully;}

5)save的另外一個重載方法處理的邏輯同上,需要注意的是兩個save方法當檔案儲存時會先產生一個tempFile然後會將調用renameTo方法將該tempFile重新命名為imageFile

BaseDiscCache有兩個擴充類,一個是不限制緩衝大小的UnlimitedDiscCache和限制緩衝時間的LimitedAgeDiscCache其中UnlimitedDiscCache很簡單它只是簡單的繼承了BaseDiscCache並未對BaseDiscCache做任何擴充。

LimitedAgeDiscCache該類實現了在緩衝中刪除被載入超過規定時間的檔案:滿足以下條件的時候就從緩衝中刪除檔案:系統目前時間-檔案的最新修改時間》maxFileAge

該類提供了兩個屬性:

1. maxFileAge(long類型)設定載入的逾時的最大時間,改時間在構造器沖初始化,一經初始化就不能改變(設定檔案存活的最長時間,當超過這個值,就刪除該檔案)

2. loadingDates (Map),該屬性是一個map類型的對象,key儲存的要緩衝的圖片檔案,而value儲存的是調用save方法是系統的目前時間,具體向loadingDates填充資料是在下面的rememberUsage方法中實現的,該方法在類中兩個save方法中調用,首先調用父類的save方法,然後在調用此方法

private void rememberUsage(String imageUri) {File file = getFile(imageUri);long currentTime = System.currentTimeMillis();file.setLastModified(currentTime);loadingDates.put(file, currentTime);}

從緩衝中擷取資料的方法為get(String imageUri)該類是重寫BaseDiscDache方法,該方法從loadingDates中擷取imageUri所代表的圖片的最新更新時間loadingDate,然後拿目前時間和loadingDate做差,如果差值大於maxFileAge也就是說查過了載入的最大時間,就刪除該imageUri所代表的file,並從loadingDates中的資料,當然如果map中沒有imageUri就不會涉及到逾時的問題,此時就把image放入map中去,具體的實現如下

@Overridepublic File get(String imageUri) {File file = super.get(imageUri);if (file != null && file.exists()) {boolean cached;Long loadingDate = loadingDates.get(file);if (loadingDate == null) {cached = false;loadingDate = file.lastModified();} else {cached = true;}if (System.currentTimeMillis() - loadingDate > maxFileAge) {file.delete();loadingDates.remove(file);} else if (!cached) {loadingDates.put(file, loadingDate);}}return file;}





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.