Android中內(nèi)存優(yōu)化的那些事 - 一個(gè)有關(guān)圖片的優(yōu)化記錄

客服群里叫喊著:這個(gè)用戶圖片不顯示了偏灿,那個(gè)用戶圖片也不顯示了扣蜻。我拿著手上一切正常的測(cè)試機(jī),what the hell……

默默地打開bugly尺棋。




滿園春色關(guān)不住封锉,遍地內(nèi)存溢出來!是的膘螟,又闖禍了成福!

內(nèi)存問題永遠(yuǎn)是既陌生又熟悉的話題,而且大多數(shù)都發(fā)生在一個(gè)叫作用戶家的手機(jī)上荆残。安卓系統(tǒng)本身不斷的在優(yōu)化奴艾,三方框架也逐漸成熟,外加手機(jī)廠商的大內(nèi)存加持脊阴,似乎內(nèi)存問題變得少見握侧,但還是不能忽視蚯瞧。

借著這次修復(fù)內(nèi)存問題的記錄,分享一些“自以為”的解決思路品擎,僅供參考埋合。ok,let’s go!

修復(fù)問題的三部曲,先復(fù)現(xiàn)萄传,再定位甚颂,最后修復(fù)。

復(fù)現(xiàn)

估計(jì)有的人會(huì)說秀菱,異痴裎埽現(xiàn)象都在那,有啥好復(fù)現(xiàn)的衍菱,沖進(jìn)代碼直接開干赶么。

修復(fù)bug永遠(yuǎn)是個(gè)驚心動(dòng)魄的事,稍微一不小心就有可能天崩地裂脊串。不是修復(fù)不完全辫呻,就是引入新問題。從起因開始了解整個(gè)緣由琼锋,一方面能加深對(duì)問題的理解放闺,同時(shí)確保最終能驗(yàn)證問題是否得到修復(fù)。

內(nèi)存的問題經(jīng)常發(fā)生在一些比較特殊的環(huán)境下缕坎,而且很多時(shí)候不一定是必現(xiàn)怖侦,往往體現(xiàn)在一些中低端機(jī)型上。所以從機(jī)型上入手可能會(huì)是一個(gè)不錯(cuò)的選擇谜叹。

最終匾寝,通過bugly查到了對(duì)應(yīng)的問題機(jī)型及系統(tǒng)版本,上各類云測(cè)平臺(tái)找到了臺(tái)云測(cè)試機(jī)叉谜。按照進(jìn)入問題頁面的幾個(gè)固定流程旗吁,反復(fù)執(zhí)行,最終鎖定了復(fù)現(xiàn)流程停局。

定位

知道問題如何復(fù)現(xiàn)很钓,接下來就是定位問題到底出在哪。通常內(nèi)存的問題董栽,會(huì)碰到兩種情況:

  1. 內(nèi)存堆積:由于特殊情況造成的頁面關(guān)閉但資源還遺漏在內(nèi)存中码倦。
  2. 內(nèi)存高占用:由于業(yè)務(wù)需要或者使用不當(dāng)導(dǎo)致內(nèi)存占用量過高。

我們先來看看這次的問題屬于哪種情況锭碳。

在Android Studio2.3及之前版本上自帶的Android monitor中袁稽,可以直觀的反應(yīng)出當(dāng)前應(yīng)用的整體內(nèi)存使用水平。[如何使用工具的分享估計(jì)大家都看膩了擒抛,這次就不再重復(fù)了推汽。]

142MB2挂伞!4跞觥莲组!進(jìn)入事故現(xiàn)場(chǎng)之前就已經(jīng)被占用了這么多內(nèi)存。難怪之后會(huì)內(nèi)存異常暖夭∏妈荆看來這次要先解決內(nèi)存高占用的問題,我們先要詳細(xì)的了解內(nèi)存的具體情況迈着,才知道從哪下手去解決竭望,無論是避免無意義的使用或者優(yōu)化必要的占用。

先強(qiáng)制gc一下裕菠,然后dump java heap咬清,看一下整體內(nèi)存里的情況,按照shallow size排序糕韧。

首當(dāng)其沖的byte數(shù)組映入眼簾枫振,大家都明白的喻圃,bitmap一直都是大客戶萤彩。我們接著分析下byte[]中的各個(gè)對(duì)象。

從數(shù)據(jù)上看斧拍,有很多大小相同的內(nèi)存使用雀扶,從理論上看應(yīng)該是有很多尺寸相同的圖片∷列冢可為什么會(huì)有這么多呢愚墓?是相同的圖片重復(fù)了?or other昂勉?

所謂耳聽為虛眼見為實(shí)浪册,如果能看到這些圖片長(zhǎng)什么樣,是否就容易做出對(duì)應(yīng)的判斷了岗照?來村象,開始行動(dòng):
來自Gracker的Android內(nèi)存優(yōu)化之三:打開MAT中的Bitmap原圖 | Performance

感謝Gracker的分享攒至,Get到一個(gè)新技能厚者。具體流程參見傳送門。主體思路就是通過MAT將對(duì)應(yīng)的byte數(shù)組另存為圖片原始文件迫吐,再用對(duì)應(yīng)的工具打開預(yù)覽即可库菲。不過我記得以前Android Studio是可以直接看的,可現(xiàn)在不知道跑哪了志膀。

步驟一:

因?yàn)锳ndroid Studio dump出來的文件mat是無法直接打開的熙宇,所以需要做一次轉(zhuǎn)換鳖擒。在Captures中找到剛剛dump出來的prof文件。右鍵 -> Export to standar .hprof 即可烫止。

步驟二:

通過MAT Eclipse Memory Analyzer Open Source Project 打開败去。

步驟三:

右鍵想要查看的對(duì)象 -> Copy -> Save Value To File。保存為xxx.data烈拒。他推薦使用Gracker分享中的gimp圆裕。Photoshop不確定是不是我使用方式有問題,在驗(yàn)證的時(shí)候一直無法正常顯示荆几。

步驟四:

查看對(duì)應(yīng)圖片的相關(guān)屬性吓妆,主體是要寬高,因?yàn)樯弦徊街斜4娴氖菆D片的原始格式文件吨铸,其中不包含對(duì)應(yīng)的參數(shù)信息行拢,所以在導(dǎo)入gimp中需要指定對(duì)應(yīng)的參數(shù)竿奏。

步驟五:

打開gimp GIMP - Downloads. 然后打開剛剛導(dǎo)出的問題寥殖。圖像類型根據(jù)實(shí)際的來,一般都是8888或者565鞍恢,選擇RGB Alpha或者RGB565房维。然后寬度與高度填寫剛剛查詢到的參數(shù)沼瘫。最后點(diǎn)擊open就能看到實(shí)際的圖片。

通過這個(gè)方式咙俩,可以直觀的查看到內(nèi)存中圖片的實(shí)際情況耿戚。然后我們就可以進(jìn)一步分析產(chǎn)生問題的實(shí)際原因。

通過以上方式阿趁,定位到了3個(gè)問題:

  1. 有大量圖片資源占用膜蛔,首頁確實(shí)有好多圖。
  2. 有暫未使用到的圖片資源占用(gone狀態(tài))脖阵。
  3. 有大量蒙版圖片占用皂股,因?yàn)樵O(shè)計(jì)師要求的效果。

解決 - 大量圖片占用

對(duì)于大量圖片占用的問題命黔,其實(shí)從以下幾個(gè)個(gè)方向來看思考問題呜呐。

  1. 從效果設(shè)計(jì)的角度來避免,盡可能的少使用滿屏圖片的方式來處理需求纷铣。但這方面我個(gè)人主張尊重設(shè)計(jì)師卵史,專業(yè)的事情交給專業(yè)的人去處理。
  2. 圖片資源本身搜立,在滿足效果的前提下以躯,盡可能的選用RGB565,也許少量圖片不明顯,但在量大的情況下忧设,節(jié)省的內(nèi)存資源還是很客觀刁标。
  3. 圖片資源在不使用的時(shí)候及時(shí)釋放。

結(jié)合以上方向來看下我們遇到的問題址晕。設(shè)計(jì)角度目前無法調(diào)整膀懈,緣由都是淚,這里就不多說了谨垃。資源本身已經(jīng)是RGB565启搂。圖片的釋放應(yīng)該是fresco的強(qiáng)項(xiàng),可從現(xiàn)象上看似乎并沒有刘陶「於模看來問題可能出在這,回ui頁面上瞄一眼匙隔,明白了疑苫。

viewpager + fragment + recyclerview,相當(dāng)于大量圖片都屬于使用狀態(tài)纷责,所以fresco不會(huì)去釋放對(duì)應(yīng)的資源捍掺。

臨時(shí)解決方案:
為了確保核心邏輯的順利,通過RxBus的方式再膳,在進(jìn)入和退出核心頁面時(shí)發(fā)送Event事件挺勿,然后在大量使用圖片的頁面注冊(cè)接收此系列事件,遍歷所有SimpleDraweeView饵史,調(diào)用其Controller的onDetach或onAttach來满钟,從而實(shí)現(xiàn)圖片資源引用的臨時(shí)釋放和加載恢復(fù)。

為什么是臨時(shí)解決方案胳喷,因?yàn)槲铱傆X得是一種取巧的方式,理論上看夭织。是不應(yīng)該直接調(diào)用方法來插手fresco的管理流程吭露。所以此處留坑,之后再次深入了解fresco的原理后再回填尊惰,也希望大家提些建議或者意見讲竿。

解決 - 暫未使用到的圖片資源占用

每個(gè)頁面中,都有處理網(wǎng)絡(luò)異常及相關(guān)數(shù)據(jù)加載異常的提示弄屡。原先的處理方式是通過include統(tǒng)一導(dǎo)入后隱藏题禀,在遇到異常的時(shí)候才顯示出來。問題就出在這膀捷,這些異常提示本身是小概率觸發(fā)迈嘹,但通過include標(biāo)簽導(dǎo)入的話,會(huì)直接實(shí)例化完成,占用內(nèi)存資源秀仲。

臨時(shí)解決方案:
改用ViewStub標(biāo)簽融痛,實(shí)現(xiàn)按需加載。

為什么又是臨時(shí)解決方案呢神僵,因?yàn)橛行C(jī)型在黑屏狀態(tài)下是切斷wifi的雁刷,當(dāng)重新進(jìn)入應(yīng)用的時(shí)候都會(huì)經(jīng)過一個(gè)聯(lián)網(wǎng)的過程,所以會(huì)先觸發(fā)聯(lián)網(wǎng)異常保礼,ViewStub只能加載一次沛励,加載完后就占用內(nèi)存了。

解決 - 蒙版圖片

之前為了在圖片上顯示文字但又不想被圖案所影響炮障,所以在上面加一層陰影蒙版來保證字體的顯示效果侯勉。習(xí)慣用fresco:overlayImage的方法來實(shí)現(xiàn)。但這種實(shí)現(xiàn)方式會(huì)造成蒙版本身是一個(gè)獨(dú)立的內(nèi)存資源铝阐。

解決方法:
嘗試通過Processor的方式址貌,預(yù)先把蒙版與要顯示的圖片合成,使得在內(nèi)存中只保留一份資源徘键。

結(jié)果

通過以上優(yōu)化方式练对,同樣的機(jī)型再次檢測(cè),內(nèi)存占用下來了....

總結(jié)

這次從內(nèi)存高占用入手吹害,解決了由于內(nèi)存使用量過高導(dǎo)致的內(nèi)存溢出螟凭。等之后遇到內(nèi)存遺留問題時(shí),再來補(bǔ)下文它呀。

內(nèi)存問題的排查與解決算是一個(gè)老生常談的話題螺男,因?yàn)檫m配等等情況往往又是一個(gè)比較棘手的問題。開發(fā)的時(shí)候很難發(fā)現(xiàn)纵穿,所以建議一個(gè)需求完成后都例行的檢查下內(nèi)存狀況下隧,看下是否有問題后者需要調(diào)整的部分。

原文鏈接: Android中內(nèi)存優(yōu)化的那些事 - 一個(gè)有關(guān)圖片的優(yōu)化記錄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谓媒,一起剝皮案震驚了整個(gè)濱河市淆院,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌句惯,老刑警劉巖土辩,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異抢野,居然都是意外死亡拷淘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門指孤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來启涯,“玉大人,你說我怎么就攤上這事∈藕浚” “怎么了扁瓢?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)补君。 經(jīng)常有香客問我引几,道長(zhǎng),這世上最難降的妖魔是什么挽铁? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任伟桅,我火速辦了婚禮,結(jié)果婚禮上叽掘,老公的妹妹穿的比我還像新娘楣铁。我一直安慰自己,他們只是感情好更扁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布盖腕。 她就那樣靜靜地躺著,像睡著了一般浓镜。 火紅的嫁衣襯著肌膚如雪溃列。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天膛薛,我揣著相機(jī)與錄音听隐,去河邊找鬼。 笑死哄啄,一個(gè)胖子當(dāng)著我的面吹牛雅任,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咨跌,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼沪么,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了虑润?” 一聲冷哼從身側(cè)響起成玫,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拳喻,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猪腕,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冗澈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了陋葡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亚亲。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捌归,到底是詐尸還是另有隱情肛响,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布惜索,位于F島的核電站特笋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏巾兆。R本人自食惡果不足惜猎物,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望角塑。 院中可真熱鬧蔫磨,春花似錦、人聲如沸圃伶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窒朋。三九已至搀罢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炼邀,已是汗流浹背魄揉。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拭宁,地道東北人洛退。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像杰标,于是被迫代替她去往敵國(guó)和親兵怯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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