內(nèi)存使用策略優(yōu)化

  • 謹(jǐn)慎使用large heap

android設(shè)備由于軟硬件的差異,heap閥值不同送漠,特殊情況下可以在manifest中使用largeheap=true聲明一個(gè)更大的heap空間,使用getLargeMemoryClass()來(lái)獲取到這個(gè)更大的空間浩姥。但是要謹(jǐn)慎使用脱衙,因?yàn)轭~外的空間會(huì)影響到系統(tǒng)整體的用戶體驗(yàn),并且會(huì)使每次gc的運(yùn)行時(shí)間更長(zhǎng)善炫。切換任務(wù)時(shí)性能大打折扣撩幽,large heap并不一定能獲取到更大的heap.

  • 綜合考慮設(shè)備內(nèi)存閾值與其他因素設(shè)計(jì)合適的緩存大小

例如,在設(shè)計(jì)ListView或者GridView的Bitmap LRU緩存的時(shí)候箩艺,需要考慮的點(diǎn)有:
應(yīng)用程序剩下了多少可用的內(nèi)存空間?

有多少圖片會(huì)被一次呈現(xiàn)到屏幕上窜醉?有多少圖片需要事先緩存好以便快速滑動(dòng)時(shí)能夠立即顯示到屏幕?

設(shè)備的屏幕大小與密度是多少? 
* 一個(gè)xhdpi的設(shè)備會(huì)比hdpi需要一個(gè)更大的Cache來(lái)hold住同樣數(shù)量的圖片舅桩。
* 不同的頁(yè)面針對(duì)Bitmap的設(shè)計(jì)的尺寸與配置是什么酱虎,大概會(huì)花費(fèi)多少內(nèi)存?
* 頁(yè)面圖片被訪問(wèn)的頻率擂涛?是否存在其中的一部分比其他的圖片具有更高的訪問(wèn)頻繁读串?如果是,也許你想要保存那些最常訪問(wèn)的到內(nèi)存中撒妈,或者為不同組別的位圖(按訪問(wèn)頻率分組)設(shè)置多個(gè)LruCache容器恢暖。
  • onLowMemory() 與onTrimMemory()

Android可以在不同的應(yīng)用當(dāng)中隨意切換。為了讓background轉(zhuǎn)到foreground, 每一個(gè)background都會(huì)占用一定的內(nèi)存狰右。系統(tǒng)會(huì)根據(jù)內(nèi)存的使用情況決定回收部分background的應(yīng)用內(nèi)存杰捂。background的應(yīng)用從暫停狀態(tài)恢復(fù)到foreground,比較快棋蚌,如果從kill狀態(tài)恢復(fù)比較慢嫁佳。

  • 資源文件需要選擇合適的文件夾進(jìn)行存放

我們知道hdpi/xhdpi/xxhdpi等等不同dpi的文件夾下的圖片在不同的設(shè)備上會(huì)經(jīng)過(guò)scale的處理。例如我們只在hdpi的目錄下放置了一張100100的圖片谷暮,那么根據(jù)換算關(guān)系蒿往,xxhdpi
的手機(jī)去引用那張圖片就會(huì)被拉伸到200200。需要注意到在這種情況下湿弦,內(nèi)存占用是會(huì)顯著提高的瓤漏。對(duì)于不希望被拉伸的圖片,需要放到assets或者nodpi的目錄下。

  • Try catch某些大內(nèi)存分配的操作

在某些情況下蔬充,我們需要事先評(píng)估那些可能發(fā)生OOM的代碼蝶俱,對(duì)于這些可能發(fā)生OOM的代碼,加入catch機(jī)制饥漫,可以考慮在catch里面嘗試一次降級(jí)的內(nèi)存分配操作榨呆。例如decode bitmap的時(shí)候,catch到OOM趾浅,可以嘗試把采樣比例再增加一倍之后愕提,再次嘗試decode。

  • 謹(jǐn)慎使用static對(duì)象

因?yàn)閟tatic的生命周期過(guò)長(zhǎng)皿哨,和應(yīng)用的進(jìn)程保持一致浅侨,使用不當(dāng)很可能導(dǎo)致對(duì)象泄漏,在Android中應(yīng)該謹(jǐn)慎使用static對(duì)象证膨。

  • 特別留意單例對(duì)象中不合理的持有

雖然單例模式簡(jiǎn)單實(shí)用如输,提供了很多便利性,但是因?yàn)閱卫纳芷诤蛻?yīng)用保持一致央勒,使用不合理很容易出現(xiàn)持有對(duì)象的泄漏不见。

  • 珍惜Services資源

如果你的應(yīng)用需要在后臺(tái)使用service,除非它被觸發(fā)并執(zhí)行一個(gè)任務(wù)崔步,否則其他時(shí)候Service都應(yīng)該是停止?fàn)顟B(tài)稳吮。另外需要注意當(dāng)這個(gè)service完成任務(wù)之后因?yàn)橥V箂ervice失敗而引起的內(nèi)存泄漏。 當(dāng)你啟動(dòng)一個(gè)Service井濒,系統(tǒng)會(huì)傾向?yàn)榱吮A暨@個(gè)Service而一直保留Service所在的進(jìn)程灶似。這使得進(jìn)程的運(yùn)行代價(jià)很高,因?yàn)橄到y(tǒng)沒(méi)有辦法把Service所占用的RAM空間騰出來(lái)讓給其他組件瑞你,另外Service還不能被Paged out酪惭。這減少了系統(tǒng)能夠存放到LRU緩存當(dāng)中的進(jìn)程數(shù)量,它會(huì)影響應(yīng)用之間的切換效率者甲,甚至?xí)?dǎo)致系統(tǒng)內(nèi)存使用不穩(wěn)定春感,從而無(wú)法繼續(xù)保持住所有目前正在運(yùn)行的service。 建議使用IntentService虏缸,它會(huì)在處理完交代給它的任務(wù)之后盡快結(jié)束自己鲫懒。更多信息,請(qǐng)閱讀Running in a Background Service刽辙。

  • 優(yōu)化布局層次窥岩,減少內(nèi)存消耗

越扁平化的視圖布局,占用的內(nèi)存就越少扫倡,效率越高谦秧。我們需要盡量保證布局足夠扁平化,當(dāng)使用系統(tǒng)提供的View無(wú)法實(shí)現(xiàn)足夠扁平的時(shí)候考慮使用自定義View來(lái)達(dá)到目的撵溃。

  • 謹(jǐn)慎使用“抽象”編程

很多時(shí)候疚鲤,開(kāi)發(fā)者會(huì)使用抽象類(lèi)作為”好的編程實(shí)踐”,因?yàn)槌橄竽軌蛱嵘a的靈活性與可維護(hù)性缘挑。然而集歇,抽象會(huì)導(dǎo)致一個(gè)顯著的額外內(nèi)存開(kāi)銷(xiāo):他們需要同等量的代碼用于可執(zhí)行,那些代碼會(huì)被mapping到內(nèi)存中语淘,因此如果你的抽象沒(méi)有顯著的提升效率诲宇,應(yīng)該盡量避免他們。

  • 使用nano protobufs序列化數(shù)據(jù)

Protocol buffers是由Google為序列化結(jié)構(gòu)數(shù)據(jù)而設(shè)計(jì)的惶翻,一種語(yǔ)言無(wú)關(guān)姑蓝,平臺(tái)無(wú)關(guān),具有良好的擴(kuò)展性吕粗。類(lèi)似XML纺荧,卻比XML更加輕量,快速颅筋,簡(jiǎn)單宙暇。如果你需要為你的數(shù)據(jù)實(shí)現(xiàn)序列化與協(xié)議化,建議使用nano protobufs议泵。關(guān)于更多細(xì)節(jié)占贫,請(qǐng)參考protobuf readme的”Nano version”章節(jié)。

  • 謹(jǐn)慎使用依賴注入框架

使用類(lèi)似Guice或者RoboGuice等框架注入代碼先口,在某種程度上可以簡(jiǎn)化你的代碼型奥。下面是使用RoboGuice前后的對(duì)比圖:

  • 謹(jǐn)慎使用多進(jìn)程

使用多進(jìn)程可以把應(yīng)用中的部分組件運(yùn)行在單獨(dú)的進(jìn)程當(dāng)中,這樣可以擴(kuò)大應(yīng)用的內(nèi)存占用范圍池充,但是這個(gè)技術(shù)必須謹(jǐn)慎使用桩引,絕大多數(shù)應(yīng)用都不應(yīng)該貿(mào)然使用多進(jìn)程,一方面是因?yàn)槭褂枚噙M(jìn)程會(huì)使得代碼邏輯更加復(fù)雜收夸,另外如果使用不當(dāng)坑匠,它可能反而會(huì)導(dǎo)致顯著增加內(nèi)存。當(dāng)你的應(yīng)用需要運(yùn)行一個(gè)常駐后臺(tái)的任務(wù)卧惜,而且這個(gè)任務(wù)并不輕量厘灼,可以考慮使用這個(gè)技術(shù)。

一個(gè)典型的例子是創(chuàng)建一個(gè)可以長(zhǎng)時(shí)間后臺(tái)播放的Music Player咽瓷。
如果整個(gè)應(yīng)用都運(yùn)行在一個(gè)進(jìn)程中设凹,當(dāng)后臺(tái)播放的時(shí)候,前臺(tái)的那些UI資源也沒(méi)有辦法得到釋放茅姜。
類(lèi)似這樣的應(yīng)用可以切分成2個(gè)進(jìn)程:一個(gè)用來(lái)操作UI闪朱,另外一個(gè)給后臺(tái)的Service月匣。
  • 使用ProGuard來(lái)剔除不需要的代碼

ProGuard能夠通過(guò)移除不需要的代碼,重命名類(lèi)奋姿,域與方法等等對(duì)代碼進(jìn)行壓縮锄开,優(yōu)化與混淆。使用ProGuard可以使得你的代碼更加緊湊称诗,這樣能夠減少mapping代碼所需要的內(nèi)存空間萍悴。

  • 謹(jǐn)慎使用第三方libraries

很多開(kāi)源的library代碼都不是為移動(dòng)網(wǎng)絡(luò)環(huán)境而編寫(xiě)的,如果運(yùn)用在移動(dòng)設(shè)備上寓免,并不一定適合癣诱。即使是針對(duì)Android而設(shè)計(jì)的library,也需要特別謹(jǐn)慎袜香,特別是在你不知道引入的library具體做了什么事情的時(shí)候撕予。例如,其中一個(gè)library使用的是nano protobufs, 而另外一個(gè)使用的是micro protobufs蜈首。這樣一來(lái)嗅蔬,在你的應(yīng)用里面就有2種protobuf的實(shí)現(xiàn)方式。這樣類(lèi)似的沖突還可能發(fā)生在輸出日志疾就,加載圖片澜术,緩存等等模塊里面。另外不要為了1個(gè)或者2個(gè)功能而導(dǎo)入整個(gè)library猬腰,如果沒(méi)有一個(gè)合適的庫(kù)與你的需求相吻合鸟废,你應(yīng)該考慮自己去實(shí)現(xiàn),而不是導(dǎo)入一個(gè)大而全的解決方案姑荷。
考慮不同的實(shí)現(xiàn)方式來(lái)優(yōu)化內(nèi)存占用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盒延,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鼠冕,更是在濱河造成了極大的恐慌添寺,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件懈费,死亡現(xiàn)場(chǎng)離奇詭異计露,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)憎乙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)票罐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人泞边,你說(shuō)我怎么就攤上這事该押。” “怎么了阵谚?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵蚕礼,是天一觀的道長(zhǎng)烟具。 經(jīng)常有香客問(wèn)我,道長(zhǎng)奠蹬,這世上最難降的妖魔是什么净赴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮罩润,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翼馆。我一直安慰自己割以,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布应媚。 她就那樣靜靜地躺著严沥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪中姜。 梳的紋絲不亂的頭發(fā)上消玄,一...
    開(kāi)封第一講書(shū)人閱讀 51,763評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音丢胚,去河邊找鬼翩瓜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛携龟,可吹牛的內(nèi)容都是我干的兔跌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼峡蟋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坟桅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蕊蝗,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤仅乓,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蓬戚,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體夸楣,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年子漩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了裕偿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡痛单,死狀恐怖嘿棘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旭绒,我是刑警寧澤鸟妙,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布焦人,位于F島的核電站,受9級(jí)特大地震影響重父,放射性物質(zhì)發(fā)生泄漏花椭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一房午、第九天 我趴在偏房一處隱蔽的房頂上張望矿辽。 院中可真熱鬧,春花似錦郭厌、人聲如沸袋倔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宾娜。三九已至,卻和暖如春扇售,著一層夾襖步出監(jiān)牢的瞬間前塔,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工承冰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留华弓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓困乒,卻偏偏與公主長(zhǎng)得像该抒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子顶燕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

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