Android性能優(yōu)化之內(nèi)存篇

android的內(nèi)存優(yōu)化一般從以下幾個方面考慮:

  • 內(nèi)存泄漏
  • 內(nèi)存抖動
  • Bitmap
  • 代碼質(zhì)量優(yōu)化

內(nèi)存泄漏

內(nèi)存泄漏的本質(zhì):不合理的引用導致引用者對象的生命周期>被引用者對象的生命周期剑逃。當回收被引用者對象時發(fā)現(xiàn)該對象還在被引用狀態(tài),無法被回收怨咪,就出現(xiàn)了內(nèi)存泄漏啤呼。

常見的內(nèi)存泄漏場景:

  • 非靜態(tài)匿名內(nèi)部類

比如經(jīng)典的在一個Activity里new一個非static 的Handler對象省核、在Activity里new了一個非靜態(tài)的Thread或者Runnable。還有很多類似的若河,尤其是在Activity或者Fragment內(nèi)引用一個非靜態(tài)的匿名內(nèi)部類時平道,這個類都會持有外部類闯估,相當于持有了context灼舍,極易導致context無法被回收,然后就內(nèi)存泄漏睬愤。

解決方法:我們可以把這個內(nèi)部類設置為靜態(tài)的片仿;或者不要使用內(nèi)部類,在外面寫個類尤辱;如果涉及到Context的必須持有問題,用Application的Context厢岂,因為其生命周期較長且唯一光督,可以不用回收,這樣就不會泄漏塔粒。

  • Static 關(guān)鍵字修飾的成員變量

我們知道结借,jvm層面static修飾的變量是放在方法區(qū)的,方法區(qū)是永久代卒茬,基本上不會發(fā)送GC船老,或者說其發(fā)送GC的條件非常苛刻圃酵,而且在java1.8后出現(xiàn)了元空間柳畔,回收更是遙遙無期,也就是說static修飾的變量的生命周期跟你的APP應用生命周期一樣郭赐,如果你的static修飾的成員變量是Context或者持有Context時薪韩,那就會導致這個變量回收不掉,會莫名其妙用了很多內(nèi)存,我們每次啟動一個Activity都會new一個Context對象俘陷,如此反復你的內(nèi)存很快就爆掉了罗捎。

解決方法:我們在寫程序時不要用static修飾類似占用大資源的對象(例如Context,View)拉盾。

  • 單例模式

這個跟上面的static原理是一樣的桨菜,因為單例模式是static的,其生命周期很長捉偏,所以要特別小心其持有對象導致內(nèi)存泄漏雷激。例如:常見的觀察者模式+單例模式時,我們會在Activity里實現(xiàn)某個接口(觀察者接口)告私,然后把這個接口add到單例模式的ArrayList(被觀察者)屎暇,這個過程就相當于單例對象持有了一個Activity對象,如果在Activity destroy時沒有把這個Activity從ArrayList里remove掉驻粟,那就造成內(nèi)存泄漏了根悼。

解決辦法:單例模式里持有變量時要注意其生命周期的管理,有+也有-蜀撑,這樣才安全挤巡。另外在這種情況里,我們可以適當合理地使用WeakReference酷麦。

  • 集合類

當一個集合使用完后沒有清空其持有的對象矿卑。例如:我們往ArrayList里add一個對象時,有的時候我們把是把一個對象add進去沃饶,但是ArrayList真正持有的是這個對象的引用母廷,所以即使我們把add的這個對象置null,但是還會依然持有對象的引用糊肤,也就等于還持有另外對象琴昆。

解決辦法:當集合不用時,要清空然后置null馆揉。例如:arrayList.clear();arrayList=null;

  • 資源對象未關(guān)閉

例如:registerBroadcast最后沒有unregisterBroadcast业舍;數(shù)據(jù)庫操作的cursor沒有close;stream流未關(guān)閉升酣;Bitmap沒有recycle等舷暮;

解決辦法:關(guān)閉或者釋放相關(guān)的信息

  • 其他情況

例如:在ListView里沒有復用好View而是創(chuàng)建了大量的View;Webview使用沒有關(guān)閉噩茄;

內(nèi)存泄漏分析下面、跟蹤、監(jiān)測的工具:

  1. Android Studio的Memory;
  2. MAT(Memory Analysis Tools);
  3. Heap Viewer;
  4. Allocation Tracker;
  5. LeakCanary;

至于如何利用這些工具進行內(nèi)存的分析巢墅,后續(xù)我會慢慢補上诸狭。
以上都是理論知識券膀,也是普遍的問題存在,而且相對來說比較容易理解驯遇,大部分開發(fā)人員也熟知芹彬,真正的提升需要在實踐中,所以有時間大家可以參考外面文章的同時自己多實踐叉庐。


內(nèi)存抖動

所謂的內(nèi)存抖動就是短時間里舒帮,內(nèi)存出現(xiàn)了反復的波動,其出現(xiàn)的原因主要是因為短時間內(nèi)陡叠,我們寫代碼時創(chuàng)建了大量的對象玩郊,頻繁地觸發(fā)了GC機制回收對象,如果回收的速度趕不上你創(chuàng)建的速度枉阵,極有可能就OOM了译红,而且創(chuàng)建了大量的對象再回收會導致磁盤空間占用比較分散,不利于整體分配內(nèi)存兴溜,會影響內(nèi)存利用率和使用效率等侦厚。避免內(nèi)存抖動注意以下幾種:

  • 避免for循環(huán)、while循環(huán)里new了很多對象拙徽;
  • 避免View的onDraw()方法里創(chuàng)建對象刨沦;
  • 避免在引用api時創(chuàng)建了大量對象,比如java的字符串拼接api膘怕;
  • 避免創(chuàng)建大量的Bitmap想诅,盡量用內(nèi)存池進行管理;
  • 避免創(chuàng)建大量的View岛心, 盡可能復用来破;
  • 其他的能夠復用的盡量復用對象,用對象池進行管理鹉梨;

其實內(nèi)存抖動還是比較容易定位的讳癌,這一塊的分析和修改也沒有太大的難度,就不做過多的分析了存皂。


Bitmap的使用

在很多的項目中,Bitmap占用的內(nèi)存達到了整個App占用內(nèi)存的50%逢艘,甚至更高旦袋。Bitmap的優(yōu)化一般從如下幾個方面考慮:

  • 避免加載過大的圖片;
  • 及時釋放不用的Bitmap它改;
    android在早期版本會把Bitmap占用的內(nèi)存放在Native里疤孕,中間(大概2.2后)轉(zhuǎn)到java heap層了,后面(8.0)又轉(zhuǎn)到Native層了央拖。所以什么時候釋放祭阀,如何釋放Bitmap占用的內(nèi)存是我們要考慮的重點鹉戚,例如RecyclerView、ListView专控、ViewPager加載View抹凳,當滑動后View不可見時Bitmap的回收。
  • Bimap緩沖池的使用伦腐,盡可能復用以前分配的內(nèi)存赢底;
    可以參考GlideBitmapPool的設計。
  • 適當?shù)腤eakRefrence使用柏蘑;
    主要是利于GC回收內(nèi)存幸冻。
  • 根據(jù)不同分辨率合理配置圖片;
    理解不同分辨率和density下圖片所占用的內(nèi)存咳焚,進行圖片配置洽损。
  • 采取合理的圖片壓縮技術(shù);
    主要考慮的參數(shù)有inTargetDensity革半,inSampleSize碑定,inJustDecodeBounds,inPreferredConfig督惰,inBitmap等不傅,要理解這些參數(shù)的含義(比較簡單)。
  • 利用緩存機制在業(yè)務層面根據(jù)不同的圖片使用頻繁度進行多緩存池+不同的緩存機制進行優(yōu)化

關(guān)于Bitmap推薦一篇文章https://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=403263974&idx=1&sn=b0315addbc47f3c38e65d9c633a12cd6&scene=21#wechat_redirect


代碼質(zhì)量

就是寫代碼過程里要注意一些小細節(jié)赏胚。

  • 盡量不用或者少用枚舉访娶,可以用IntDef/@StringDef + @interface來進行限定參數(shù),因為枚舉占內(nèi)存大且容易來帶類型不安全問題觉阅。
  • 當界面不可見時崖疤,適當?shù)蒯尫艃?nèi)存,避免內(nèi)存占用過高同時也可避免進程被回收,因為不可見的進程內(nèi)存占用越高被回收的概率越高《Э鳎可以在Activity的onTrimMemory(int level)方法里做贷揽。
  • 使用Android系統(tǒng)自帶的數(shù)據(jù)存儲結(jié)構(gòu)代碼Java自帶的,例如SparseArray取代HashMap赖钞。
  • 使用HashMap、ArrayList這些存儲結(jié)構(gòu)時,要適當考慮容量般码,盡可能避免無端擴容帶來的性能浪費。
  • 利用好Java的引用類型(強軟弱虛)乱顾,合理選擇引用類型板祝。
  • 謹慎使用多進程。
  • 謹慎使用largeHeap走净。
  • 謹慎使用shareprefercnce券时。
  • 用好ProGuard剔除不必要的代碼孤里。
  • 選好基礎(chǔ)數(shù)據(jù)類型,能用byte的不用int橘洞,能用int的不用long捌袜,盡量不用包裝類型。
  • 注意dex文件和.so文件數(shù)量問題震檩,加載過多的這類文件內(nèi)存也會增加很多琢蛤。
  • 可以考慮利用好匿名共享內(nèi)存,但是要注意管理好抛虏,匿名共享內(nèi)存自身是管殺不管埋的博其。
  • Parcelable序列化對象時不能太大,否則會爆掉導致crash迂猴。
  • 盡量選用系統(tǒng)資源慕淡,如String,Color沸毁,Style等峰髓。
  • Log信息輸出的選擇上,最后選用aop式息尺,在正式代碼里直接不把日志輸出代碼編譯進去携兵。
  • 優(yōu)化線程的分配,過多的線程分配和線程切換浪費資源(內(nèi)存+CPU)搂誉。在App開發(fā)過程中徐紧,我們經(jīng)常會引入很多第三方SDK,在這些SDK里各自都可能存在多線程或者多線程池的情況炭懊,我們盡可能選擇可配置線程的SDK使用并级,最后統(tǒng)一用一個線程池進行管理線程。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侮腹,一起剝皮案震驚了整個濱河市嘲碧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌父阻,老刑警劉巖愈涩,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異加矛,居然都是意外死亡钠署,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門荒椭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人舰蟆,你說我怎么就攤上這事趣惠±旯鳎” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵味悄,是天一觀的道長草戈。 經(jīng)常有香客問我,道長侍瑟,這世上最難降的妖魔是什么唐片? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮涨颜,結(jié)果婚禮上费韭,老公的妹妹穿的比我還像新娘。我一直安慰自己庭瑰,他們只是感情好星持,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著弹灭,像睡著了一般督暂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上穷吮,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天逻翁,我揣著相機與錄音,去河邊找鬼捡鱼。 笑死八回,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的堰汉。 我是一名探鬼主播辽社,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼翘鸭!你這毒婦竟也來了滴铅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤就乓,失蹤者是張志新(化名)和其女友劉穎汉匙,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體生蚁,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡噩翠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了邦投。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伤锚。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖志衣,靈堂內(nèi)的尸體忽然破棺而出屯援,到底是詐尸還是另有隱情猛们,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布狞洋,位于F島的核電站弯淘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吉懊。R本人自食惡果不足惜庐橙,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望借嗽。 院中可真熱鬧态鳖,春花似錦淹魄、人聲如沸郁惜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兆蕉。三九已至,卻和暖如春缤沦,著一層夾襖步出監(jiān)牢的瞬間虎韵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工缸废, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留包蓝,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓企量,卻偏偏與公主長得像测萎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子届巩,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

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