【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實現(xiàn)圖片緩存機(jī)制_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實現(xiàn)圖片緩存機(jī)制_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實現(xiàn)圖片緩存機(jī)制_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實現(xiàn)圖片緩存機(jī)制_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實現(xiàn)圖片緩存機(jī)制_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】Android中怎么實現(xiàn)圖片緩存機(jī)制

這期內(nèi)容當(dāng)中在下將會給大家?guī)碛嘘P(guān)Android中怎么實現(xiàn)圖片緩存機(jī)制,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。Android圖片緩存機(jī)制的深入理解Android加載一張圖片到用戶界面是很簡單的,但是當(dāng)一次加載多張圖片時,情況就變得復(fù)雜起來。很多情況下(像ListView、GridView或ViewPager等組件),屏幕上已顯示的圖片和即將滑動到當(dāng)前屏幕上的圖片數(shù)量基本上是沒有限制的。這些組件通過重用已經(jīng)移除屏幕的子視圖來將降低內(nèi)存的使用,垃圾回收器也會及時釋放那些已經(jīng)不再使用的已下載的圖片,這些都是很好的方法,但是為了保持一個流暢的、快速加載的用戶界面,就應(yīng)該避免當(dāng)再次回到某個頁面時而重新處理圖片。內(nèi)存緩存和磁盤緩存可以幫我們做到這些,它們允許組件快速地重新加載已處理好的圖片。使用內(nèi)存緩存內(nèi)存緩存允許快速地訪問圖片,但它以占用App寶貴的內(nèi)存為代價。LruCache類(APILevel4的SupportLibrary也支持)特別適合來做圖片緩存,它使用一個強(qiáng)引用的LinkedHashMap來保存最近使用的對象,并且會在緩存數(shù)量超出預(yù)設(shè)的大小之前移除最近最少使用的對象。說明:以前流行的內(nèi)存緩存方案是使用軟引用或弱引用來緩存圖片,然而現(xiàn)在不推薦這樣做了,因為從android2.3(APILevel9)起,垃圾收集器更傾向于先回收軟引用或弱引用,這樣就使它們變得低效。另外在Android3.0(APILevel11)之前,圖片的像素數(shù)據(jù)是存儲在本地內(nèi)存(nativememory)中的,它以一種不可預(yù)測的方式釋放,因此可能會導(dǎo)致App超過內(nèi)存限制甚至崩潰。為了給LruCache設(shè)置一個合適的大小,以下是應(yīng)該考慮的一些因素:1.你的Activity或App的可用內(nèi)存是多少?2.一次展示到屏幕上的圖片是多少?有多少圖片需要預(yù)先準(zhǔn)備好以便隨時加載到屏幕?3.設(shè)備的屏幕尺寸和密度是多少?像GalaxyNexus這樣的高分辨率(xhdpi)設(shè)備比NexusS這樣分辨率(hdpi)的設(shè)備在緩存相同數(shù)量的圖片時需要更大的緩存空間。4.圖片的尺寸和配置是怎樣的?每張圖片會占用多少內(nèi)存?5.圖片的訪問頻率如何?是否有一些圖片比另一些訪問更加頻繁?如果這樣的話,或許可以將某些圖片一直保存在內(nèi)存里或者針對不同的圖片分組設(shè)置不同的LruCache對象。6.你能否平衡圖片質(zhì)量和數(shù)量之間的關(guān)系?有時候存儲更多低質(zhì)量的圖片更加有用,當(dāng)在需要的時候,再通過后臺任務(wù)下載高質(zhì)量的圖片。這里沒有一個具體的大小和計算公式適用于所有的App,你需要分析你的使用情況并得到一個合適的方案。當(dāng)一個緩存太小時會導(dǎo)致無益的額外的開銷,而緩存太大時也可能會引起Java.lang.OutOfMemory異常,另外緩存越大,留給App其他部分的內(nèi)存相應(yīng)就越小。這里是一個為圖片設(shè)置LruCache的示例:private

LruCache<String,

Bitmap>

mMemoryCache;

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

...

//

Get

max

available

VM

memory,

exceeding

this

amount

will

throw

an

//

OutOfMemory

exception.

Stored

in

kilobytes

as

LruCache

takes

an

//

int

in

its

constructor.

final

int

maxMemory

=

(int)

(Runtime.getRuntime().maxMemory()

/

1024);

//

Use

1/8th

of

the

available

memory

for

this

memory

cache.

final

int

cacheSize

=

maxMemory

/

8;

mMemoryCache

=

new

LruCache<String,

Bitmap>(cacheSize)

{

@Override

protected

int

sizeOf(String

key,

Bitmap

bitmap)

{

//

The

cache

size

will

be

measured

in

kilobytes

rather

than

//

number

of

items.

return

bitmap.getByteCount()

/

1024;

}

};

...

}

public

void

addBitmapToMemoryCache(String

key,

Bitmap

bitmap)

{

if

(getBitmapFromMemCache(key)

==

null)

{

mMemoryCache.put(key,

bitmap);

}

}

public

Bitmap

getBitmapFromMemCache(String

key)

{

return

mMemoryCache.get(key);

}說明:在上述例子中,我們分配了應(yīng)用內(nèi)存的1/8作為緩存大小,在一個normal/hdpi的設(shè)備上最少也有4MB(32/8)的大小。一個800*480分辨率的屏幕上的一個填滿圖片的GridView大概占用1.5MB(800*480*4byte)的內(nèi)存,因此該Cache至少可以緩存2.5頁這樣的圖片。當(dāng)加載一張圖片到ImageView時,首先檢查LruCache,如果找到圖片,就直接用來更新ImageView,如果沒找到就開啟一個后臺線程來處理:public

void

loadBitmap(int

resId,

ImageView

imageView)

{

final

String

imageKey

=

String.valueOf(resId);

final

Bitmap

bitmap

=

getBitmapFromMemCache(imageKey);

if

(bitmap

!=

null)

{

mImageView.setImageBitmap(bitmap);

}

else

{

mImageView.setImageResource(R.drawable.image_placeholder);

BitmapWorkerTask

task

=

new

BitmapWorkerTask(mImageView);

task.execute(resId);

}

}上述線程中,在解碼圖片之后,也需要把它添加到內(nèi)存緩存中:class

BitmapWorkerTask

extends

AsyncTask<Integer,

Void,

Bitmap>

{

...

//

Decode

image

in

background.

@Override

protected

Bitmap

doInBackground(Integer...

params)

{

final

Bitmap

bitmap

=

decodeSampledBitmapFromResource(

getResources(),

params[0],

100,

100));

addBitmapToMemoryCache(String.valueOf(params[0]),

bitmap);

return

bitmap;

}

...

}使用磁盤緩存雖然內(nèi)存緩存在快速訪問最近使用的圖片時是很有用的,但是你無法保證你所需要的圖片就在緩存中,類似GridView這樣展示大量數(shù)據(jù)的組件可以很輕易地就占滿內(nèi)存緩存。你的App也可能被類似電話這樣的任務(wù)打斷,當(dāng)App被切換到后臺后也可能被殺死,內(nèi)存緩存也可能被銷毀,一旦用戶回到之前的界面,你的App依然要重新處理每個圖片。磁盤緩存可以用來輔助存儲處理過的圖片,當(dāng)內(nèi)存緩存中圖片不可用時,可以從磁盤緩存中查找,從而減少加載次數(shù)。當(dāng)然,從磁盤讀取圖片要比從內(nèi)存讀取慢并且讀取時間是不可預(yù)期的,因此需要使用后臺線程來讀取。說明:ContentProvider可能是一個合適的存儲頻繁訪問的圖片的地方,比如在ImageGallery應(yīng)用中。這里的示例代碼是從Android源代碼中剝離出來的DiskLruCache,以下是更新后的實例代碼,在內(nèi)存緩存的基礎(chǔ)上增加了磁盤緩存:private

DiskLruCache

mDiskLruCache;

private

final

Object

mDiskCacheLock

=

new

Object();

private

boolean

mDiskCacheStarting

=

true;

private

static

final

int

DISK_CACHE_SIZE

=

1024

*

1024

*

10;

//

10MB

private

static

final

String

DISK_CACHE_SUBDIR

=

"thumbnails";

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

...

//

Initialize

memory

cache

...

//

Initialize

disk

cache

on

background

thread

File

cacheDir

=

getDiskCacheDir(this,

DISK_CACHE_SUBDIR);

new

InitDiskCacheTask().execute(cacheDir);

...

}

class

InitDiskCacheTask

extends

AsyncTask<File,

Void,

Void>

{

@Override

protected

Void

doInBackground(File...

params)

{

synchronized

(mDiskCacheLock)

{

File

cacheDir

=

params[0];

mDiskLruCache

=

DiskLruCache.open(cacheDir,

DISK_CACHE_SIZE);

mDiskCacheStarting

=

false;

//

Finished

initialization

mDiskCacheLock.notifyAll();

//

Wake

any

waiting

threads

}

return

null;

}

}

class

BitmapWorkerTask

extends

AsyncTask<Integer,

Void,

Bitmap>

{

...

//

Decode

image

in

background.

@Override

protected

Bitmap

doInBackground(Integer...

params)

{

final

String

imageKey

=

String.valueOf(params[0]);

//

Check

disk

cache

in

background

thread

Bitmap

bitmap

=

getBitmapFromDiskCache(imageKey);

if

(bitmap

==

null)

{

//

Not

found

in

disk

cache

//

Process

as

normal

final

Bitmap

bitmap

=

decodeSampledBitmapFromResource(

getResources(),

params[0],

100,

100));

}

//

Add

final

bitmap

to

caches

addBitmapToCache(imageKey,

bitmap);

return

bitmap;

}

...

}

public

void

addBitmapToCache(String

key,

Bitmap

bitmap)

{

//

Add

to

memory

cache

as

before

if

(getBitmapFromMemCache(key)

==

null)

{

mMemoryCache.put(key,

bitmap);

}

//

Also

add

to

disk

cache

synchronized

(mDiskCacheLock)

{

if

(mDiskLruCache

!=

null

&&

mDiskLruCache.get(key)

==

null)

{

mDiskLruCache.put(key,

bitmap);

}

}

}

public

Bitmap

getBitmapFromDiskCache(String

key)

{

synchronized

(mDiskCacheLock)

{

//

Wait

while

disk

cache

is

started

from

background

thread

while

(mDiskCacheStarting)

{

try

{

mDiskCacheLock.wait();

}

catch

(InterruptedException

e)

{}

}

if

(mDiskLruCache

!=

null)

{

return

mDiskLruCache.get(key);

}

}

return

nul

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論