Android中有沒有必要調(diào)用Bitmap的recycle()

在Android應(yīng)用里欢揖,最耗費(fèi)內(nèi)存的就是圖片資源她混。而且在Android系統(tǒng)中坤按,讀取位圖Bitmap時(shí),分給虛擬機(jī)中的圖片的堆棧大小只有8M来累,如果超出了嘹锁,就會(huì)出現(xiàn)OutOfMemory異常。所以瘤运,對(duì)于圖片的內(nèi)存優(yōu)化拯坟,是Android應(yīng)用開發(fā)中比較重要的內(nèi)容郁季。

1) 要及時(shí)回收Bitmap的內(nèi)存

Bitmap類有一個(gè)方法recycle()似枕,從方法名可以看出意思是回收凿歼。這里就有疑問了答憔,Android系統(tǒng)有自己的垃圾回收機(jī)制,可以不定期的回收掉不使用的內(nèi)存空間蓉驹,當(dāng)然也包括Bitmap的空間态兴。那為什么還需要這個(gè)方法呢?

Bitmap類的構(gòu)造方法都是私有的,所以開發(fā)者不能直接new出一個(gè)Bitmap對(duì)象敢订,只能通過BitmapFactory類的各種靜態(tài)方法來實(shí)例化一個(gè)Bitmap楚午。仔細(xì)查看BitmapFactory的源代碼可以看到矾柜,生成Bitmap對(duì)象最終都是通過JNI調(diào)用方式實(shí)現(xiàn)的怪蔑。所以喧枷,加載Bitmap到內(nèi)存里以后隧甚,是包含兩部分內(nèi)存區(qū)域的。簡單的說帽借,一部分是Java部分的宜雀,一部分是C部分的悴品。這個(gè)Bitmap對(duì)象是由Java部分分配的苔严,不用的時(shí)候系統(tǒng)就會(huì)自動(dòng)回收了欠窒,但是那個(gè)對(duì)應(yīng)的C可用的內(nèi)存區(qū)域岖妄,虛擬機(jī)是不能直接回收的,這個(gè)只能調(diào)用底層的功能釋放福扬。所以需要調(diào)用recycle()方法來釋放C部分的內(nèi)存铛碑。從Bitmap類的源代碼也可以看到涛菠,recycle()方法里也的確是調(diào)用了JNI方法了的碗暗。

那如果不調(diào)用recycle(),是否就一定存在內(nèi)存泄露呢?也不是的噪奄。Android的每個(gè)應(yīng)用都運(yùn)行在獨(dú)立的進(jìn)程里,有著獨(dú)立的內(nèi)存碰缔,如果整個(gè)進(jìn)程被應(yīng)用本身或者系統(tǒng)殺死了,內(nèi)存也就都被釋放掉了梗肝,當(dāng)然也包括C部分的內(nèi)存。

Android對(duì)于進(jìn)程的管理是非常復(fù)雜的坝锰。簡單的說,Android系統(tǒng)的進(jìn)程分為幾個(gè)級(jí)別愕把,系統(tǒng)會(huì)在內(nèi)存不足的情況下殺死一些低優(yōu)先級(jí)的進(jìn)程嚣镜,以提供給其它進(jìn)程充足的內(nèi)存空間菊匿。在實(shí)際項(xiàng)目開發(fā)過程中,有的開發(fā)者會(huì)在退出程序的時(shí)候使用Process.killProcess(Process.myPid())的方式將自己的進(jìn)程殺死佩厚,但是有的應(yīng)用僅僅會(huì)使用調(diào)用Activity.finish()方法的方式關(guān)閉掉所有的Activity。

經(jīng)驗(yàn)分享:

Android手機(jī)的用戶,根據(jù)習(xí)慣不同煞额,可能會(huì)有兩種方式退出整個(gè)應(yīng)用程序:一種是按Home鍵直接退到桌面;另一種是從應(yīng)用程序的退出按鈕或者按Back鍵退出程序。那么從系統(tǒng)的角度來說,這兩種方式有什么區(qū)別呢?按Home鍵涩僻,應(yīng)用程序并沒有被關(guān)閉,而是成為了后臺(tái)應(yīng)用程序。按Back鍵坪圾,一般來說兽泄,應(yīng)用程序關(guān)閉了胃珍,但是進(jìn)程并沒有被殺死,而是成為了空進(jìn)程(程序本身對(duì)退出做了特殊處理的不考慮在內(nèi))填抬。

Android系統(tǒng)已經(jīng)做了大量進(jìn)程管理的工作,這些已經(jīng)可以滿足用戶的需求读拆。個(gè)人建議,應(yīng)用程序在退出應(yīng)用的時(shí)候不需要手動(dòng)殺死自己所在的進(jìn)程鸵闪。對(duì)于應(yīng)用程序本身的進(jìn)程管理檐晕,交給Android系統(tǒng)來處理就可以了。應(yīng)用程序需要做的蚌讼,是盡量做好程序本身的內(nèi)存管理工作辟灰。

一般來說篡石,如果能夠獲得Bitmap對(duì)象的引用芥喇,就需要及時(shí)的調(diào)用Bitmap的recycle()方法來釋放Bitmap占用的內(nèi)存空間,而不要等Android系統(tǒng)來進(jìn)行釋放凰萨。

下面是釋放Bitmap的示例代碼片段继控。

// 先判斷是否已經(jīng)回收

if(bitmap != null && !bitmap.isRecycled()){

// 回收并且置為null

bitmap.recycle();

bitmap = null;

}

System.gc();

從上面的代碼可以看到,bitmap.recycle()方法用于回收該Bitmap所占用的內(nèi)存胖眷,接著將bitmap置空武通,最后使用System.gc()調(diào)用一下系統(tǒng)的垃圾回收器進(jìn)行回收,可以通知垃圾回收器盡快進(jìn)行回收珊搀。這里需要注意的是冶忱,調(diào)用System.gc()并不能保證立即開始進(jìn)行回收過程,而只是為了加快回收的到來境析。

如何調(diào)用recycle()方法進(jìn)行回收已經(jīng)了解了囚枪,那什么時(shí)候釋放Bitmap的內(nèi)存比較合適呢?一般來說派诬,如果代碼已經(jīng)不再需要使用Bitmap對(duì)象了,就可以釋放了眶拉。釋放內(nèi)存以后千埃,就不能再使用該Bitmap對(duì)象了,如果再次使用忆植,就會(huì)拋出異常放可。所以一定要保證不再使用的時(shí)候釋放。比如朝刊,如果是在某個(gè)Activity中使用Bitmap耀里,就可以在Activity的onStop()或者onDestroy()方法中進(jìn)行回收。

2) 捕獲異常

因?yàn)锽itmap是吃內(nèi)存大戶拾氓,為了避免應(yīng)用在分配Bitmap內(nèi)存的時(shí)候出現(xiàn)OutOfMemory異常以后Crash掉冯挎,需要特別注意實(shí)例化Bitmap部分的代碼。通常咙鞍,在實(shí)例化Bitmap的代碼中房官,一定要對(duì)OutOfMemory異常進(jìn)行捕獲。

以下是代碼示例续滋。

Bitmap bitmap = null;

try {

// 實(shí)例化Bitmap

bitmap = BitmapFactory.decodeFile(path);

} catch (OutOfMemoryError e) {

//

}

if (bitmap == null) {

// 如果實(shí)例化失敗 返回默認(rèn)的Bitmap對(duì)象

return defaultBitmapMap;

}

這里對(duì)初始化Bitmap對(duì)象過程中可能發(fā)生的OutOfMemory異常進(jìn)行了捕獲翰守。如果發(fā)生了OutOfMemory異常,應(yīng)用不會(huì)崩潰疲酌,而是得到了一個(gè)默認(rèn)的Bitmap圖蜡峰。

經(jīng)驗(yàn)分享:

很多開發(fā)者會(huì)習(xí)慣性的在代碼中直接捕獲Exception。但是對(duì)于OutOfMemoryError來說朗恳,這樣做是捕獲不到的湿颅。因?yàn)镺utOfMemoryError是一種Error,而不是Exception粥诫。在此僅僅做一下提醒油航,避免寫錯(cuò)代碼而捕獲不到OutOfMemoryError。

3) 緩存通用的Bitmap對(duì)象

有時(shí)候怀浆,可能需要在一個(gè)Activity里多次用到同一張圖片劝堪。比如一個(gè)Activity會(huì)展示一些用戶的頭像列表,而如果用戶沒有設(shè)置頭像的話揉稚,則會(huì)顯示一個(gè)默認(rèn)頭像,而這個(gè)頭像是位于應(yīng)用程序本身的資源文件中的熬粗。

如果有類似上面的場景搀玖,就可以對(duì)同一Bitmap進(jìn)行緩存。如果不進(jìn)行緩存驻呐,盡管看到的是同一張圖片文件灌诅,但是使用BitmapFactory類的方法來實(shí)例化出來的Bitmap芳来,是不同的Bitmap對(duì)象。緩存可以避免新建多個(gè)Bitmap對(duì)象猜拾,避免內(nèi)存的浪費(fèi)即舌。

經(jīng)驗(yàn)分享:

Web開發(fā)者對(duì)于緩存技術(shù)是很熟悉的。其實(shí)在Android應(yīng)用開發(fā)過程中挎袜,也會(huì)經(jīng)常使用緩存的技術(shù)顽聂。這里所說的緩存有兩個(gè)級(jí)別,一個(gè)是硬盤緩存盯仪,一個(gè)是內(nèi)存緩存紊搪。比如說,在開發(fā)網(wǎng)絡(luò)應(yīng)用過程中全景,可以將一些從網(wǎng)絡(luò)上獲取的數(shù)據(jù)保存到SD卡中耀石,下次直接從SD卡讀取,而不從網(wǎng)絡(luò)中讀取爸黄,從而節(jié)省網(wǎng)絡(luò)流量滞伟。這種方式就是硬盤緩存。再比如炕贵,應(yīng)用程序經(jīng)常會(huì)使用同一對(duì)象梆奈,也可以放到內(nèi)存中緩存起來,需要的時(shí)候直接從內(nèi)存中讀取鲁驶。這種方式就是內(nèi)存緩存鉴裹。

4) 壓縮圖片

如果圖片像素過大,使用BitmapFactory類的方法實(shí)例化Bitmap的過程中钥弯,需要大于8M的內(nèi)存空間径荔,就必定會(huì)發(fā)生OutOfMemory異常。這個(gè)時(shí)候該如何處理呢?如果有這種情況脆霎,則可以將圖片縮小总处,以減少載入圖片過程中的內(nèi)存的使用,避免異常發(fā)生睛蛛。

使用BitmapFactory.Options設(shè)置inSampleSize就可以縮小圖片鹦马。屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一。即如果這個(gè)值為2忆肾,則取出的縮略圖的寬和高都是原始圖片的1/2荸频,圖片的大小就為原始大小的1/4。

如果知道圖片的像素過大客冈,就可以對(duì)其進(jìn)行縮小旭从。那么如何才知道圖片過大呢?

使用BitmapFactory.Options設(shè)置inJustDecodeBounds為true后,再使用decodeFile()等方法,并不會(huì)真正的分配空間和悦,即解碼出來的Bitmap為null退疫,但是可計(jì)算出原始圖片的寬度和高度,即options.outWidth和options.outHeight鸽素。通過這兩個(gè)值褒繁,就可以知道圖片是否過大了。

BitmapFactory.Options opts = new BitmapFactory.Options();

// 設(shè)置inJustDecodeBounds為true

opts.inJustDecodeBounds = true;

// 使用decodeFile方法得到圖片的寬和高

BitmapFactory.decodeFile(path, opts);

// 打印出圖片的寬和高

Log.d("example", opts.outWidth + "," + opts.outHeight);

在實(shí)際項(xiàng)目中馍忽,可以利用上面的代碼棒坏,先獲取圖片真實(shí)的寬度和高度,然后判斷是否需要跑縮小舵匾。如果不需要縮小俊抵,設(shè)置inSampleSize的值為1。如果需要縮小坐梯,則動(dòng)態(tài)計(jì)算并設(shè)置inSampleSize的值徽诲,對(duì)圖片進(jìn)行縮小。需要注意的是吵血,在下次使用BitmapFactory的decodeFile()等方法實(shí)例化Bitmap對(duì)象前谎替,別忘記將opts.inJustDecodeBound設(shè)置回false。否則獲取的bitmap對(duì)象還是null蹋辅。

經(jīng)驗(yàn)分享:

如果程序的圖片的來源都是程序包中的資源钱贯,或者是自己服務(wù)器上的圖片,圖片的大小是開發(fā)者可以調(diào)整的侦另,那么一般來說秩命,就只需要注意使用的圖片不要過大,并且注意代碼的質(zhì)量褒傅,及時(shí)回收Bitmap對(duì)象弃锐,就能避免OutOfMemory異常的發(fā)生。

如果程序的圖片來自外界殿托,這個(gè)時(shí)候就特別需要注意OutOfMemory的發(fā)生霹菊。一個(gè)是如果載入的圖片比較大,就需要先縮小;另一個(gè)是一定要捕獲異常支竹,避免程序Crash旋廷。




原文:http://blog.csdn.net/android_destiny/article/details/51782508

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市礼搁,隨后出現(xiàn)的幾起案子饶碘,更是在濱河造成了極大的恐慌,老刑警劉巖馒吴,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扎运,死亡現(xiàn)場離奇詭異卑雁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)绪囱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莹捡,“玉大人鬼吵,你說我怎么就攤上這事±河” “怎么了齿椅?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長启泣。 經(jīng)常有香客問我涣脚,道長,這世上最難降的妖魔是什么寥茫? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任遣蚀,我火速辦了婚禮,結(jié)果婚禮上纱耻,老公的妹妹穿的比我還像新娘芭梯。我一直安慰自己,他們只是感情好弄喘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布玖喘。 她就那樣靜靜地躺著,像睡著了一般蘑志。 火紅的嫁衣襯著肌膚如雪累奈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天急但,我揣著相機(jī)與錄音澎媒,去河邊找鬼。 笑死羊始,一個(gè)胖子當(dāng)著我的面吹牛旱幼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播突委,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柏卤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了匀油?” 一聲冷哼從身側(cè)響起缘缚,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎敌蚜,沒想到半個(gè)月后桥滨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年齐媒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蒲每。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡喻括,死狀恐怖邀杏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情唬血,我是刑警寧澤望蜡,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站拷恨,受9級(jí)特大地震影響脖律,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜腕侄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一小泉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兜挨,春花似錦膏孟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至噪舀,卻和暖如春魁淳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背与倡。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工界逛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纺座。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓息拜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親净响。 傳聞我的和親對(duì)象是個(gè)殘疾皇子少欺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 2021期待與你一起共事,點(diǎn)擊查看崗位[http://www.reibang.com/p/6f4d67fa406...
    閑庭閱讀 16,638評(píng)論 0 75
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評(píng)論 25 707
  • 參考資料 目錄 Bitmap BitmapFactory Bitmap加載方法 Bitmap | Drawable...
    玄策閱讀 2,768評(píng)論 0 7
  • ‘「無戒365極限挑戰(zhàn)日更營第5天」 2017.10.20 上午馋贤,接到小弟打來電話赞别,說鄉(xiāng)下小姑發(fā)病住院了,要我給妹...
    彭臻華閱讀 326評(píng)論 0 1
  • 夜 漆黑的夜 月華灑了一地滿滿的蒼白 風(fēng) 凄涼的風(fēng) 纖雨落了一臉冷冷的疲憊 樹 凄美的樹 影子拉長了喧鬧繁華之后的...
    1個(gè)勇敢的心閱讀 303評(píng)論 0 1