編輯:關於Android編程
話說,從mta上報的數據上來看,我們的app出現了3起OOM(out of memery):
java.lang.Throwable: java.lang.OutOfMemoryError at com.tencent.stat.a.d.(Unknown Source) at com.tencent.stat.g.uncaughtException(Unknown Source) at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693) at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690) at dalvik.system.NativeStart.main(Native Method)
從錯誤堆棧是顯然是看不出任何問題的,那麼問題會出現在什麼地方呢?
我們猜測了一下幾種可能?
1、存在內存洩露。
2、不需要的bitmap沒有被釋放。
那麼問題是否就是上面這兩種情況呢?
帶著這個問題,我們首先驗證下,內存是否占用真的很大。
首先,開啟android studio內存占用圖標展示工具,可以看到內存占用77M,
重啟應用,各頁面點擊一下,相關路徑踩一踩,不踩不知道,一踩就嚇一跳,啟動的時候,直觀的從圖中可以看到,內存占用40M,然而,切換到發現tab,發現內存彪到70M,然後,切換其他頁面,如下圖:
比如切換到,消息,我的,等等,發現內存依然,居高不下了,滑動發現頁的時候,內存占用依然有標高的趨勢。
我們使用dumpsys meminfocom.xxx.xxx (app包名),查看內存占用情況如下圖:
cat 一下進程,可以看到最大占用(這裡包括虛擬機和原生)如下圖:
不用說了,這個的優化,那麼怎麼辦?
依然是寄出我們android studio上的內存分析工具,如下圖:
首先,GC一下 ,然後在導出hprof文件,進行分析 。首先分析是否存在內存洩露:
如上圖,並沒有發現有內存洩露的activity存在,這也歸功於我們平常有事沒事都會隨手分析一下是否有內存洩露,如果有,早就解決了,等不到我。
那麼既然沒有內存洩露的Activity,那麼我們何不看一下對象的內存占用情況呢?
如是:如圖
這裡,我們很輕易的抓住了第一個凶手,bitmap。
其原因是因為這裡做了一個打分的自定義view,這個view的分數是繪制出來的,之所以沒有用字體,是因為引入一個字體庫會增加包大小(雖然可以有些工具可以抽取僅僅需要的字體元素來縮小字體庫,但我們考慮到實現一個打分效果的自定義view的成本也不大,因此並沒有考慮抽取字體庫),得不償失,然而,這個自定義view中每個實例,都擁有0到9加上。的bitmap;
然而他被顯示到列表的時候,可想而知,會有多少張圖,優化起來相當簡單,將這些bitmap使用靜態變量保存,這樣所有實例只會公用一份bitmap列表了:
,好吧,繼續走查其他對象的內存占用,我們發現:
PopoFeed對象占用內存也較多:但,一層一層的剝下去,最終發現是PopoFeed對象中的User對象裡面的UserTag占用內存較多:
可以想象,一個popofeed如果有20多條評論,10幾個人打分,那這樣就有30個User對象在popofeed對象中,30*3K,那就是90K,這些對view展示無用的數據吃內存也是非常恐怖的,所以,拉起後台同學,對返回的數據做了優化。同時,我們發現,返回的數據多,GSON轉model所需要的內存也較多,所以,服務端對返回數據做清洗還是挺有必要的。
,好吧,到了第三階段,我們繼續走查,發現fragment占用內存較多,其實不難推測,使用fragmentManger管理fragment ,你看到的是一個頁面,但其實上,默認是會加載1-2個到緩存中的,從源碼中可以看出:
所以,你當前在發現頁,實際上,大廳,消息都已經加載進內存了,那麼這時候的做法就是在重寫setUserVisibleHint
方法,當fragment可見的時候,將數據渲染到view上,當fragment不可見的時候,把view上數據清理掉,不過或許也有更好的方法,如果有,歡迎告訴我~。
然而,還有一個更加可惡的問題,那就是當fragment執行onDestroyView方法後,該fragment並沒有釋放掉內存,這也就是為什麼切換到發現之後,在切換其他fragment內存居高不下的首要原因,我的解決辦法是:
因為從引用樹上看到:
findFragment被fragmentManger引用著,其在執行onDestroyView的時候,一些該釋放的內存得不到釋放,因此采取以上辦法。
好吧,經過三個小小的優化,我們來看看,內存占用:
對比發現頁:
發現頁內存占用現在是 48M,同比之前的77M,減少了37%。
然後切換到我的
我們發現內存占用只有28.58M。
對於內存峰值方面的對比,
(165516-120792)/165516 = 27%
總結這次的優化:
1、當內存中類的多個對象引用的資源不變的時候,請使用靜態,這樣,這些資源就只有一份,減少不必要的內存占用。
2、json轉model是一個很耗時的過程,減少json中不必要的字段,不僅可以加快json轉model的時間,還能降低內存占用。
3、fragment不可見的時候,實際上可能還占用著你的內存,要懂得小心釋放不必要的內存。
騰訊自主研發,榮獲2015年十佳組件第一名的“tMemoryMonitor”內存洩漏分析工具。該騰訊內部工具已經在騰訊WeTest官網內免費開放給用戶使用
TMM下載地址:http://wetest.qq.com/cloud/index.php/index/TMM
【工具簡介】
tMemoryMonitor簡稱TMM,是一款運行時C/C++內存洩漏檢測工具。TMM認為在進程退出時,內存中沒有被釋放且沒有指針指向的無主內存塊即為內存洩漏,並進而引入垃圾回收機制,在進程退出時檢測出堆內存中所有沒有被引用的內存單元,因而內存洩漏檢測准確率為100%。
五一放假,閒著沒事,裝了最新的ubutun16.04,然後打算順道把android開發環境移植到ubuntu上來體驗一下。 1.首先下載了Android stu
前言我原想直接跳過這些osgi中基礎知識,直接從osgi應用的一些中級篇或者高級篇開始的,後來想到osgi中的ServiceListener、ServiceTracker
介紹A text field allows the user to type text into your app. It can be either single li
Android recycleView的應用和點擊事件效果圖:長按是刪除:下面代碼:MainActivity 類public class MainActivity ext