背景
洩露場景臨時性記憶體洩漏Java是垃圾回收語言的一種,其優點是開發者無需特意管理記憶體分配,降低了應用由於區域性故障導致崩潰,同時防止未釋放的記憶體把堆疊(heap)擠爆的可能,所以寫出來的程式碼更為安全。
不幸的是,在Java中仍存在很多容易導致記憶體洩漏的邏輯可能。如果不小心,你的Android應用很容易浪費掉未釋放的記憶體,輕則應用卡頓,重則導致記憶體用光丟擲OOM。
1.context引用
context引用 況會持有外部類的引用,一旦執行耗時操作,會造成記憶體回收不及時,從而造成OOM。典型例子就是Handler,當Handler宣告為非靜態內部類時會持有外部類(例如Activity)的引用。
2.非靜態內部類
這種情況會持有外部類的引用,一旦執行耗時操作,會造成記憶體回收不及時,從而造成OOM。典型例子就是Handler,當Handler宣告為非靜態內部類時會持有外部類(例如Activity)的引用。
3.匿名類
相似地,匿名類也維護了外部類的引用。所以記憶體洩漏很容易發生,當你在Activity中定義了匿名的AsyncTsk。當非同步任務在後臺執行耗時任務期間,Activity不幸被銷燬了,這個被AsyncTask持有的Activity例項就不會被垃圾回收器回收,直到非同步任務結束。
4.監聽器
App開發中我們都需要和監聽器打交道,通常一個應用當中會用到很多監聽器,我們會呼叫一個控制元件的諸如addXXXListener()等方法來增加監聽器,但往往在釋放物件的時候卻沒有記住去刪除這些監聽器,一旦監聽器裡執行了耗時操作,物件就無法回收,從而增加了記憶體洩漏的機會。
5.資源物件未關閉
資源性物件比如(Cursor遊標,Stream流,BroadCastReceiver等)往往都用了一些緩衝,我們在不使用的時候或者在使用完之後,應該及時關閉它們比如close()方法,以便它們的緩衝及時回收記憶體。Bitmap要先recyler(),在置為null。
6.不要在執行頻率高的方法中建立物件
在自定義View中onDraw和onMesaure這兩個方法一般執行頻率很高,一旦使用不當,會建立大量物件,頻繁GC,會導致應用變卡頓。
7.WebView造成的洩露
當我們不要使用WebView物件時,應該呼叫它的destory()函式來銷燬它,並釋放其佔用的記憶體,否則其佔用的記憶體長期也不能被回收,從而造成記憶體洩露。
8.構造Adapter時,沒有使用快取的ConvertView
ListView在載入佈局時如果不使用快取的ConvertView,而是每次重新載入,就容易造成記憶體洩漏,應用卡頓。
永久性記憶體洩漏1.全域性變數
全域性變數的記憶體永遠不會被回收,一般app中都會定義一個常量類來存放這些資料,但是能少用全域性變數就少用,畢竟要一直佔用記憶體,如果使用建議只儲存一些基本資料型別,切記不要持有context,activity,fragment,view的引用。這種錯誤一般在單例模式中比較常見。
2.屬性動畫
從Android3.0開始,Google提供了屬性動畫,屬性動畫中有一類無限迴圈的動畫,如果在Activity中播放此類動畫並且在onDestroy()方法中沒有停止該動畫,那麼動畫會一直迴圈下去,儘管在介面上已經無法看不到動畫了,但這個時候Activity的View會被動畫持有,而View又持有Activity,最終Activity無法釋放。
3.系統服務
當你使用系統服務的時候,可以註冊監聽器,會導致服務持有Context的引用,如果在Activity銷燬的時候,沒有登出掉監聽器,就會導致記憶體洩漏。
解決方法弱引用(耗時操作持有的context等引用可以用弱引用)使用LeakCanary工具查詢記憶體洩漏(該工具會會自動分析context是否引起記憶體洩漏)Android Studio自帶分析工具Profiler(使用該工具可以實時檢視記憶體使用狀況)- 零基礎安卓開發起步(三)
- Android程序管理:Framework層概念
- 僅 2 位 Java 開發,使用小程式上線一款 App
- 使用VSCode 打包你的第一個flutter應用(安卓篇)
- 阿里面了9次,位元組撈了offer?Android開發狗25次大廠面試辛酸淚
- 方舟編譯器是將java程式碼像C++靜態編譯,那麼為什麼安卓當時一開始為啥不用C++?
- 現在還有沒有那種純電視,沒有開關機動畫,沒有內建資源,不是安卓系統的?
- 專科渣校,嘔心瀝血在家3個月“拿下”330頁PDF,終於拿下阿里OFFer
- 神一樣的操作,真的牛逼了!Android Jetpack Compose 最全上手指南
- Android開發者必知的記憶體、效能優化細節