![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)圖片緩存機(jī)制_第1頁(yè)](http://file4.renrendoc.com/view/e53992ebd2f3d713ec941a471d1b0fba/e53992ebd2f3d713ec941a471d1b0fba1.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)圖片緩存機(jī)制_第2頁(yè)](http://file4.renrendoc.com/view/e53992ebd2f3d713ec941a471d1b0fba/e53992ebd2f3d713ec941a471d1b0fba2.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)圖片緩存機(jī)制_第3頁(yè)](http://file4.renrendoc.com/view/e53992ebd2f3d713ec941a471d1b0fba/e53992ebd2f3d713ec941a471d1b0fba3.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)圖片緩存機(jī)制_第4頁(yè)](http://file4.renrendoc.com/view/e53992ebd2f3d713ec941a471d1b0fba/e53992ebd2f3d713ec941a471d1b0fba4.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)圖片緩存機(jī)制_第5頁(yè)](http://file4.renrendoc.com/view/e53992ebd2f3d713ec941a471d1b0fba/e53992ebd2f3d713ec941a471d1b0fba5.gif)
版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 連續(xù)梁拆除專(zhuān)項(xiàng)施工方案
- 市場(chǎng)營(yíng)銷(xiāo)趨勢(shì)分析報(bào)告
- 科技改變運(yùn)動(dòng)器材
- 教學(xué)策略與新技術(shù)講座
- 2021年10月乘務(wù)員模擬試卷與答案解析2
- 2025年度智能電網(wǎng)建設(shè)合同相對(duì)性協(xié)議
- 新版華東師大版八年級(jí)數(shù)學(xué)下冊(cè)《17.3.2一次函數(shù)的圖象1》聽(tīng)評(píng)課記錄21
- 2025年度建筑工程合同風(fēng)險(xiǎn)管理論文匯編
- 五年級(jí)上冊(cè)數(shù)學(xué)聽(tīng)評(píng)課記錄《4.1 比較圖形的面積》(2)-北師大版
- 九年物理教師聽(tīng)評(píng)課記錄
- 藥企銷(xiāo)售總經(jīng)理競(jìng)聘
- 開(kāi)封市第一屆職業(yè)技能大賽健康照護(hù)項(xiàng)目技術(shù)文件(國(guó)賽)
- 公路電子收費(fèi)系統(tǒng)安裝合同范本
- 醫(yī)院培訓(xùn)課件:《傷口評(píng)估與測(cè)量》
- 2021年全國(guó)高考物理真題試卷及解析(全國(guó)已卷)
- 期末試卷(試題)-2024-2025學(xué)年四年級(jí)上冊(cè)數(shù)學(xué)滬教版
- 《第一單元口語(yǔ)交際:即興發(fā)言》教案-2023-2024學(xué)年六年級(jí)下冊(cè)語(yǔ)文統(tǒng)編版
- 綜合實(shí)踐項(xiàng)目 制作水族箱飼養(yǎng)淡水魚(yú) 教學(xué)設(shè)計(jì)-2024-2025學(xué)年魯科版生物六年級(jí)上冊(cè)
- 公轉(zhuǎn)私付款合同模板
- 安徽省2024年高考語(yǔ)文模擬試卷及答案5
- 關(guān)于餐飲合同范本
評(píng)論
0/150
提交評(píng)論