記一次詭異的OOM坑
阿新 • • 發佈:2019-01-07
OOM,即OutOfMemory。作為Android裝置常見的效能問題,經常見於圖片大量載入的場景。然而博主這次碰到的OOM,卻是由一個意想不到又合情合理的問題導致。由於是半路接手一個正在開發的專案,著實被坑了一把。
一. 場景描述:
在一個Activity中,會非同步生成一張二維碼圖片。不過這個功能顯然是後來匆忙加的,因為二維碼Bitmap並沒有快取(專案其它地方的圖片都是用Glide)。這樣導致每次進入Activity,都會重新建立一個Bitmap。
- 在使用App較長時間後,再次進入這個Activity偶爾會導致OOM。
二. 嘗試解決
這個二維碼Bitmap,畫素為700*700.我們嘗試使用Glide載入到ImageView中,這樣只會在第一次進入Activity時,才會通過ZXing建立二維碼Bitmap。
不過在經過測試之後,仍然會出現OOM。我們開啟Android Profiler,來監測記憶體情況:
對比進入Activity前後的記憶體佔用情況:
Graphics的記憶體佔用突然增長了51M。
而且是每次進入Activity,都會發生如此劇烈的抖動,除了二維碼圖片,還有其它的問題。
註釋掉二維碼圖片的生成,然後再次觀察測試。情況依舊,記憶體佔用峰值瞬時增加50-100M:
三. 大家來找茬
疑點:
在有點懵圈的時刻,不經意間瞟了一眼介面,發現了可疑之處:
開始看見這塊白色背景時,還以為是設定了color;
切到相關佈局xml一看:
android:background="@drawable
很好,去目錄下看看這張圖:
簡直嚇死寶寶了,一張1034*1398的無碼高清PNG大圖…..
再次嘗試:
android:background="#ffffff"
順滑多了:
至此問題解決,罪魁禍首就是那一張高解析度無碼高清大圖。
四. 小結
- Android Profiler是好工具。
- 任何圖片的載入,都會出現增加記憶體開銷。圖片快取的意義也就在於此—–通過快取策略控制圖片的記憶體消耗。然而直接在XML中設定載入圖片,就沒辦法使用快取了。
- 本來這個問題應該很容易發現的,但半路接手專案,還不太熟悉,以至於走了彎路。當然,那張二維碼圖片仍然是應當快取起來的。
- 要跟產品、美工溝通好,這種神奇的背景圖片就不應當用,它會拖慢載入速度,增加記憶體壓力。而且還有更好的處理方式。比如9Patch,VectorDrawable,等等。