Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android-Universal-Image-Loader學習筆記(一)

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

編輯:關於Android編程

Android-Universal-Image-Loader是一個開源項目,負責處理圖片的加載和緩存。閒暇之時看了一些源代碼,特記錄之。

說道圖片文件(磁盤)緩存,需要考慮如下的因素

1) 緩存文件的名稱的定義

2) 緩存的大小

3) 緩存文件的方式:比如限時保存文件等,圖片壓縮後的格式,壓縮率等等。

該項目對磁盤緩存保存文件時對文件名稱的修改也做了支持:在緩存文件時對文件名稱的修改提供了兩種方式,每一種方式對應了一個Java類

1) HashCodeFileNameGenerator,該類負責獲取文件名稱的hashcode然後轉換成字符串。

2) Md5FileNameGenerator,該類把源文件的名稱同過md5加密後保存。兩個類都繼承了FileNameGenerator接口

它們之間的關系如下圖所示

\

<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHAgYWxpZ249"left">在DefaultConfigurationFactory類中提供了一個工廠方法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;//緩存文件的保存Directory
protected 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的話,就刪除temFile
			if (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中去,具體的實現如下

@Override
	public 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;
	}





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