Android內(nèi)存優(yōu)化

為什么進(jìn)行內(nèi)存優(yōu)化?

1. app運(yùn)行內(nèi)存限制,OOM導(dǎo)致app奔潰

2. app性能:流暢性、響應(yīng)速度和用戶體驗(yàn)

獲取Android系統(tǒng)默認(rèn)給每個(gè)app分配的內(nèi)存上限: ? ? ??

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);int memoryClass = activityManager.getMemoryClass();? ? //單位為m 經(jīng)測試本人紅米3S為192M

如果超出這個(gè)限制,將會導(dǎo)致應(yīng)用OOM锭弊。


Android的內(nèi)存管理方式:

?Android系統(tǒng)的內(nèi)存分配和回收方式:

1. Android底層是Linux系統(tǒng),一個(gè) App 通常就是一個(gè)進(jìn)程對應(yīng)一個(gè)虛擬機(jī),一個(gè)虛擬機(jī)在linux系 統(tǒng)中有一個(gè)進(jìn)程與之對應(yīng)
2. GC(垃圾回收器)只在Heap(堆)剩余空間不夠時(shí)才會發(fā)出垃圾回收
3. GC觸發(fā)時(shí),所有的線程都會被暫停

App 內(nèi)存限制機(jī)制:

1. 每個(gè) App 分配的最大內(nèi)存限制,隨不同設(shè)備而不同
2. 吃內(nèi)存大戶:圖片
3. 為什么要限制:多任務(wù)系統(tǒng)要使每個(gè) App?具有足夠的內(nèi)存空間保證都能夠正常運(yùn)行

切換應(yīng)用時(shí)后臺 App?清理機(jī)制:

1. 后臺各種 App?切換時(shí)的LRU Cache(最近使用的排在最前面,最少使用的可能被清理掉)
2. 系統(tǒng)內(nèi)存不夠清理后臺 App?時(shí)候回調(diào)onTrimMemory(int level)方法

onTrimMemory(int level):
? ? ?4.0 之后提供的一個(gè)API旁舰,這個(gè) API 是提供給開發(fā)者的定庵,它的主要作用是提示開發(fā)者在系統(tǒng)內(nèi)存不足的時(shí)候秤朗,通過處理部分資源來釋放內(nèi)存肯腕,從而避免被 Android 系統(tǒng)殺死,提高應(yīng)用程序的用戶體驗(yàn).當(dāng)內(nèi)存變化時(shí)Android系統(tǒng)會根據(jù)不同等級的內(nèi)存使用情況步脓,調(diào)用這個(gè)函數(shù),并傳入對應(yīng)的等級;我們可以根據(jù)該等級的類型观谦,如果等級屬于危險(xiǎn)級別的就可以做相應(yīng)的處理,把我們 App?里面不同的內(nèi)存盡快清理掉,這樣我們的 App?內(nèi)存占用就相對小一點(diǎn),從而降低被清理掉的可能性拉盾。

監(jiān)控內(nèi)存的幾種方法:

1. 代碼:以下兩個(gè)相加就是系統(tǒng)當(dāng)前分配給這個(gè) App?的內(nèi)存大小

已經(jīng)分配的內(nèi)存大小:

float totalMemory = Runtime.getRuntime().totalMemory() * 1.0f / (1024 * 1024); 

空閑的內(nèi)存:

float freeMemory = Runtime.getRuntime().freeMemory() * 1.0f / (1024 * 1024);

2. AS的Android Monitor監(jiān)控:
3. AS的Android Device Monitor
? ? 依次點(diǎn)擊:Tools-->Android-->Android Device Monitor豁状,選中要查看的進(jìn)程,點(diǎn)擊左上角綠色水杯Update Heap-->右邊Cause GC捉偏;
? ? Heap Size:堆的大小 = Allocated:分配的大小 + Free:空閑的大小泻红;
? ? data Object和class Object如果不穩(wěn)定夭禽、不斷變大就考慮是否內(nèi)存泄漏

Android內(nèi)存優(yōu)化方法

數(shù)據(jù)結(jié)構(gòu)優(yōu)化:

1. 頻繁字符串拼接用StringBuilder
? 字符串通過+的方式進(jìn)行拼接,會產(chǎn)生中間字符串內(nèi)存塊,會被GC回收掉,同時(shí)也是效率低的,耗時(shí)較長
2. ArrayMap、SparseAray代替HashMap
3. 內(nèi)存抖動:變量使用不當(dāng)引起
? ? 比如突然申請很多變量或內(nèi)存空間,但是這個(gè)內(nèi)存空間的數(shù)據(jù)很快就用完了,過了一會又申請很多,這時(shí)如果heap的內(nèi)存不夠,GC就會回收之前的內(nèi)存,這個(gè)過程會暫停所有線程,如果這個(gè)過程在較短的時(shí)間內(nèi)重復(fù)出現(xiàn)可以從Monitor中看到鋸齒一樣的抖動,如果內(nèi)存抖動耗時(shí)比較長,就會影響 App?運(yùn)行的流暢性,用戶體驗(yàn)就會很差
4. 再小的Class也至少耗費(fèi)0.5KB
5. HashMap一個(gè)entry需要額外占用32B
6. 避免在android里面使用Enum
7. 減少bitmap的內(nèi)存占用,圖片質(zhì)量不高時(shí)可以考慮使用RBG_565
8. 萬惡的static
? ? static聲明變量的生命周期和 App?的生命周期一樣的,大量的使用谊路,會占據(jù)內(nèi)存空間不釋放讹躯,積少成多會造成內(nèi)存的不斷開銷,直至掛掉;
? ? 一般用來修飾基本數(shù)據(jù)類型或者輕量級對象缠劝,盡量避免修復(fù)集合或者大對象蜀撑,常用作修飾全局配置項(xiàng)、工具類方法剩彬、內(nèi)部類酷麦。

對象復(fù)用:

1. 復(fù)用系統(tǒng)自帶的資源(布局、資源文件等)
2. listView喉恋、GridView的convertView復(fù)用(現(xiàn)在都在用RecyclerView了吧哈~)
3. 避免在onDraw()方法里面執(zhí)行對象的創(chuàng)建

避免內(nèi)存泄漏:

1. 內(nèi)存泄漏會導(dǎo)致剩余可用 heap 內(nèi)存越來越少,頻繁觸發(fā)GC直至OOM
2. 尤其activity泄漏
? ? 被靜態(tài)集合引用沃饶;
? ? 內(nèi)部類中開啟線程會保持外部activity的引用,如果執(zhí)行耗時(shí)操作,當(dāng)activity銷毀時(shí)還未執(zhí)行完畢導(dǎo)致activity無法被回收,導(dǎo)致內(nèi)存泄漏。
3. 盡量用Application Context而不是Activity Context
4. 注意Cursor對象是否及時(shí)關(guān)閉
5. 謹(jǐn)慎handler
? ? Activity的onDestroy方法中調(diào)用handler.removeCallbacksAndMessages(null);取消所有的消息的處理轻黑,包括待處理的消息糊肤;
? ? 聲明handler的內(nèi)部類為static。
6. 頁面背景和圖片加載
? ? 設(shè)置背景和圖片的時(shí)候氓鄙,如果是純色馆揉,盡量使用color
? ? 規(guī)則圖形,盡量使用shape畫圖
? ? 稍微復(fù)雜點(diǎn)抖拦,可以使用9patch圖
? ? 不能使用9patch的情況下升酣,針對幾種主流分辨率的機(jī)型進(jìn)行切圖

內(nèi)存泄漏:邏輯上創(chuàng)建的對象(內(nèi)存塊)使用完后不用了,應(yīng)該被GC回收變成Free內(nèi)存,但由于代碼瑕疵,導(dǎo)致這塊內(nèi)存雖然不用了,但仍然被其他地方引用著,使得GC無法對其進(jìn)行回收态罪,大量的內(nèi)存泄露會導(dǎo)致OOM噩茄。

Android內(nèi)存管理之道

OOM 問題優(yōu)化:

OOM問題分析:

1. OOM的必然性和可解決性
? ? 程序開發(fā)的性能不好,超出最大內(nèi)存限制就必然發(fā)生,手機(jī)廠家在設(shè)定內(nèi)存上限的時(shí)候肯定已經(jīng)考慮過了,你的 App?如果優(yōu)化的比較好,肯定可以在手機(jī)上順暢的運(yùn)行,不會出現(xiàn)OOM問題,出現(xiàn)該問題肯定是優(yōu)化有問題。
2. OOM絕大部分發(fā)生在圖片

強(qiáng)引用复颈、軟引用:

變量的生命周期:跟其所處的環(huán)境有關(guān)绩聘,一般變量在activity的成員位置,那么他的生命周期和activity是一樣的,如果在方法里面,它的生命周期跟方法有關(guān)凿菩,方法退出了,其生命周期就結(jié)束了机杜;當(dāng)變量生命周期終止的時(shí)候,GC是會對它進(jìn)行回收的衅谷。

被軟引用包裹的變量:softReference<類型>椒拗,假設(shè)其在activity成員位置,如果在activity的活動的生命周期中会喝,內(nèi)存不夠了,對于軟引用所占有的內(nèi)存空間GC是可以對其進(jìn)行回收的,所以軟引用和強(qiáng)引用的關(guān)系是:
? ?強(qiáng)引用在生命周期里它的內(nèi)存空間是不會被回收的玩郊,而軟引用在它的生命周期里肢执,只要是內(nèi)存不夠了,那么GC是可以對其進(jìn)行回收的译红,所以在運(yùn)行的過程中有可能會出現(xiàn)這個(gè)引用變成空的了它不再指向任何一個(gè)內(nèi)存空間预茄。

優(yōu)化OOM問題的方法

1. 注意臨時(shí)Bitmap對象的及時(shí)回收(置空或recycler)GC會很快處理掉
2. 避免Bitmap浪費(fèi)
3. Try catch? 某些大內(nèi)存分配的操作
4. 加載Bitmap:縮放比例(采樣率)、解碼格式(RGB_565))侦厚、局部加載(解決大部分圖片相關(guān)OOM問題)
5. 最后推薦一個(gè)檢測 App?內(nèi)存泄露的工具
? LeakCanary(具體使用網(wǎng)上很容易查到耻陕,很簡單就可以集成,就不贅述了)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刨沦,一起剝皮案震驚了整個(gè)濱河市诗宣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌想诅,老刑警劉巖召庞,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異来破,居然都是意外死亡篮灼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門徘禁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诅诱,“玉大人,你說我怎么就攤上這事送朱∧锏矗” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵驶沼,是天一觀的道長它改。 經(jīng)常有香客問我,道長商乎,這世上最難降的妖魔是什么央拖? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上鲜戒,老公的妹妹穿的比我還像新娘专控。我一直安慰自己,他們只是感情好遏餐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布伦腐。 她就那樣靜靜地躺著,像睡著了一般失都。 火紅的嫁衣襯著肌膚如雪柏蘑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天粹庞,我揣著相機(jī)與錄音咳焚,去河邊找鬼。 笑死庞溜,一個(gè)胖子當(dāng)著我的面吹牛革半,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播流码,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼又官,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了漫试?” 一聲冷哼從身側(cè)響起六敬,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驾荣,沒想到半個(gè)月后觉阅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秘车,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年典勇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叮趴。...
    茶點(diǎn)故事閱讀 39,769評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡割笙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出眯亦,到底是詐尸還是另有隱情伤溉,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布妻率,位于F島的核電站乱顾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宫静。R本人自食惡果不足惜走净,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一券时、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伏伯,春花似錦橘洞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至弄唧,卻和暖如春适肠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背候引。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工侯养, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人背伴。 一個(gè)月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓沸毁,卻偏偏與公主長得像峰髓,于是被迫代替她去往敵國和親傻寂。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評論 2 354

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