Android優(yōu)化三:內(nèi)存泄漏

Android優(yōu)化一:提綱
Android優(yōu)化二:性能檢測
Android優(yōu)化三:內(nèi)存優(yōu)化
Android優(yōu)化四:App啟動速度優(yōu)化
Android優(yōu)化五:布局優(yōu)化
Android優(yōu)化六:性能優(yōu)化

什么是內(nèi)存泄漏拘鞋?

根據(jù) Java 內(nèi)存回收機制的“可達性分析法”含思,如果這些對象是可達的窃诉,但是這些對象是無用的被饿,就會導致內(nèi)存泄漏塞琼,內(nèi)存泄漏的積累最終導致內(nèi)存溢出隐砸。

分類

Android中內(nèi)存溢出主要分為四類:

①集合類泄漏
②單例/靜態(tài)變量造成的內(nèi)存泄漏
③匿名內(nèi)部類/非靜態(tài)內(nèi)部類
④資源未關(guān)閉造成的內(nèi)存泄漏

Q:單例為什么會導致內(nèi)存泄漏祝沸?

其實單例本身跟內(nèi)存泄漏是沒什么關(guān)系的耘分,只有在單例使用不恰單才會導致內(nèi)存泄漏。
單例導致內(nèi)存泄漏主要的原因是:單例的靜態(tài)特性使得單例的生命周期跟整個應(yīng)用的生命周期一樣長壹店。
如果我們在單例中傳入的 Context 是 Activity 的 context猜丹,當這個 Context 所對應(yīng)的 Activity 退出時,由于該 Context 的引用被單例對象所持有硅卢,其生命周期等于整個應(yīng)用程序的生命周期射窒,所以當前 Activity 退出時它的內(nèi)存并不會被回收,這就造成泄漏了将塑。
同理被 static 修飾的成員變量也是如此脉顿,其生命周期將與整個app進程生命周期一樣。

Q:handler 和非靜態(tài)內(nèi)部類為什么會導致內(nèi)存泄漏点寥?

非靜態(tài)內(nèi)部類默認會持有外部類的引用艾疟,handler 的生命周期與 Activity 的生命周期不一致,
如果 Activity 銷毀了但是 Handler 里面有未處理完的延時消息敢辩,導致 Activity 不能被 GC 回收蔽莱。

OOM異常

  • 可以通過getMemoryClass( )來獲取App的可用堆內(nèi)存,如果申請的內(nèi)存超過這個值戚长,就會造成OOM異常盗冷。
  • 可以在AndroidManifest.xml文件<applicatiion>中可以設(shè)置 android:largeHeap="true"活的更大的堆內(nèi)存。

具體細節(jié)

1同廉、Bitmap圖片過大

解決辦法:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;

圖片寬高都為原來的二分之一仪糖,即圖片為原來的四分之一。

  • bitmap.get().recycle();
    在用完Bitmap時迫肖,要及時的recycle掉锅劝。recycle并不能確定立即就會將Bitmap釋放掉,但是會給虛擬機一個暗示:“該圖片可以釋放了”蟆湖。

  • 軟引用(SoftRefrence)
    我們使用Bitmap后沒有保留對它的引用故爵,因此就無法調(diào)用Recycle函數(shù)。這時候巧妙的運用軟引用帐姻,可以使Bitmap在內(nèi)存快不足時得到有效的釋放 稠集。

但是是現(xiàn)在已經(jīng)不再推薦使用這種方式了奶段,因為從 Android 2.3 (API Level 9)開始,垃圾回收器會更傾向于回收持有軟引用或弱引用的對象剥纷,這讓軟引用和弱引用變得不再可靠痹籍。另外,Android 3.0 (API Level 11)中晦鞋,圖片的數(shù)據(jù)會存儲在本地的內(nèi)存當中蹲缠,因而無法用一種可預見的方式將其釋放锭亏,這就有潛在的風險造成應(yīng)用程序的內(nèi)存溢出并崩潰辙培。
From 郭霖的博客

  • 建議使用成熟的Glide、Picasso属划、Fresco框架來加載圖片确买。

2斤讥、界面切換

  • 看頁面布局有沒有大的圖片,比如背景圖之類的湾趾。
  • 直接把XML配置成view再放到一個容器里面芭商,避免重復加載。
  • 在頁面切換時盡可能少地重復使用一些代碼搀缠。

3铛楣、資源未關(guān)閉

  • BraodcastReceiver,ContentObserver艺普,F(xiàn)ile簸州,Cursor,Stream歧譬,Bitmap等資源的使用沒有注銷導致岸浑。
  • 在Activity銷毀時及時關(guān)閉或者注銷。

4缴罗、ListView沒有使用緩存

  • 使用的convertView進行緩存
  • 建議使用5.0出來的RecycleView替代Listview助琐。

5祭埂、Handler導致

  • 應(yīng)該申明為靜態(tài)對象面氓, 并在其內(nèi)部類中保存一個對外部類的弱引用。
  • 在Activity銷毀時及時關(guān)閉或者注銷
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //handler導致內(nèi)存泄漏;
        //當Activity銷毀時蛆橡,匿名內(nèi)部類一直持有Activity的引用舌界,無法釋放。
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //執(zhí)行邏輯
            }
        }, 10000L);
    }

6泰演、 線程導致

  • 線程產(chǎn)生內(nèi)存泄露的主要原因在于線程生命周期的不可控呻拌。
  • 將線程的內(nèi)部類,改為靜態(tài)內(nèi)部類睦焕。
  • 采用線程池, 避免程序中存在大量的Thread藐握。

7靴拱、盡量使用9path圖片

.9圖片可以任意調(diào)整大小,進行拉伸猾普。

8袜炕、使用單例造成

  • 當調(diào)用getInstance時,如果傳入的context是Activity的context初家。只要這個單例沒有被釋放偎窘,那么這個Activity也不會被釋放一直到進程退出才會釋放。
  • 使用Application的Context溜在。

9陌知、非靜態(tài)內(nèi)部類創(chuàng)建靜態(tài)實例

  • 將非靜態(tài)內(nèi)部類修改為靜態(tài)內(nèi)部類。(靜態(tài)內(nèi)部類不會隱式持有外部類)
  • Context盡量使用Application Context掖肋,因為Application的Context的生命周期比較長仆葡。

10、使用了靜態(tài)的Activity和View

  • private static View sView;
  • 應(yīng)該及時將靜態(tài)的應(yīng)用 置為null志笼,而且一般不建議將View及Activity設(shè)置為靜態(tài)浙芙。

11、屬性動畫導致的內(nèi)存泄漏

  • 屬性動畫有一類無限循環(huán)的動畫, 如果在Activity中播放此類動畫且沒有在Activity退出的時候沒有停止動畫. 盡管無法界面上看到效果, 但是創(chuàng)建這個動畫所關(guān)聯(lián)的View被動畫所持有, 而View又持有了Activity, 最終Activity無法釋放.
  • 解決方案是在onDestroy()中調(diào)用動畫的cancel()來停止動畫.

12籽腕、幀動畫導致

  • 幀動畫使用的圖片過大過多導致

終極大招:LeakCanary

LeakCanary 是一個開源的在debug版本中檢測內(nèi)存泄漏的java庫嗡呼。
LeakCanary 中文使用說明
平時寫代碼稍微注意點,再用這個檢測基本能搞定所有oom異常皇耗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末南窗,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子郎楼,更是在濱河造成了極大的恐慌万伤,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呜袁,死亡現(xiàn)場離奇詭異敌买,居然都是意外死亡,警方通過查閱死者的電腦和手機阶界,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門虹钮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人膘融,你說我怎么就攤上這事芙粱。” “怎么了氧映?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵春畔,是天一觀的道長。 經(jīng)常有香客問我,道長律姨,這世上最難降的妖魔是什么振峻? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮择份,結(jié)果婚禮上铺韧,老公的妹妹穿的比我還像新娘。我一直安慰自己缓淹,他們只是感情好哈打,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著讯壶,像睡著了一般料仗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伏蚊,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天立轧,我揣著相機與錄音,去河邊找鬼躏吊。 笑死氛改,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的比伏。 我是一名探鬼主播胜卤,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼赁项!你這毒婦竟也來了葛躏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤悠菜,失蹤者是張志新(化名)和其女友劉穎舰攒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悔醋,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡摩窃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芬骄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猾愿。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖德玫,靈堂內(nèi)的尸體忽然破棺而出匪蟀,到底是詐尸還是另有隱情,我是刑警寧澤宰僧,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響琴儿,放射性物質(zhì)發(fā)生泄漏段化。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一造成、第九天 我趴在偏房一處隱蔽的房頂上張望显熏。 院中可真熱鬧,春花似錦晒屎、人聲如沸喘蟆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蕴轨。三九已至,卻和暖如春骇吭,著一層夾襖步出監(jiān)牢的瞬間橙弱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工燥狰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留棘脐,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓龙致,卻偏偏與公主長得像蛀缝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子目代,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,152評論 25 707
  • 性能優(yōu)化系列閱讀 Android性能優(yōu)化 性能優(yōu)化 - 消除卡頓 性能優(yōu)化- 內(nèi)存優(yōu)化 性能分析工具 - Trac...
    JackChen1024閱讀 1,315評論 1 20
  • HereAndroid的內(nèi)存優(yōu)化是性能優(yōu)化中很重要的一部分内斯,而避免OOM又是內(nèi)存優(yōu)化中比較核心的一點。這是一篇關(guān)于...
    HarryXR閱讀 3,819評論 1 24
  • 李堤 河南自古稱中原像啼, 中原之中有汝南俘闯。 汝南城北二十里, 古村李堤是故園忽冻。 書名李堤知家少真朗, 俗名”勒滴”傳...
    南海老人閱讀 255評論 1 4
  • 此刻,八點四十九分僧诚,我戴著耳機在屬于自己的空間里隨機播放著德永英明的音樂遮婶。有一種感覺已經(jīng)牽絆很久了,身處在這個被縱...
    Hosn閱讀 430評論 1 3