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

下載本文檔

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

文檔簡(jiǎn)介

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

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

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

}

}上述線(xiàn)程中,在解碼圖片之后,也需要把它添加到內(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;

}

...

}使用磁盤(pán)緩存雖然內(nèi)存緩存在快速訪(fǎng)問(wèn)最近使用的圖片時(shí)是很有用的,但是你無(wú)法保證你所需要的圖片就在緩存中,類(lèi)似GridView這樣展示大量數(shù)據(jù)的組件可以很輕易地就占滿(mǎn)內(nèi)存緩存。你的App也可能被類(lèi)似電話(huà)這樣的任務(wù)打斷,當(dāng)App被切換到后臺(tái)后也可能被殺死,內(nèi)存緩存也可能被銷(xiāo)毀,一旦用戶(hù)回到之前的界面,你的App依然要重新處理每個(gè)圖片。磁盤(pán)緩存可以用來(lái)輔助存儲(chǔ)處理過(guò)的圖片,當(dāng)內(nèi)存緩存中圖片不可用時(shí),可以從磁盤(pán)緩存中查找,從而減少加載次數(shù)。當(dāng)然,從磁盤(pán)讀取圖片要比從內(nèi)存讀取慢并且讀取時(shí)間是不可預(yù)期的,因此需要使用后臺(tái)線(xiàn)程來(lái)讀取。說(shuō)明:ContentProvider可能是一個(gè)合適的存儲(chǔ)頻繁訪(fǎng)問(wèn)的圖片的地方,比如在ImageGallery應(yīng)用中。這里的示例代碼是從Android源代碼中剝離出來(lái)的DiskLruCache,以下是更新后的實(shí)例代碼,在內(nèi)存緩存的基礎(chǔ)上增加了磁盤(pán)緩存: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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論