Volley引起的記憶體洩漏--安卓怎麼查記憶體洩漏(下)
怎麼處理volley的記憶體洩漏呢
網上查了查,有說是volley的低版本的bug 升級版本 就好了 但是專案裡的volley是down下來的包,改了內部很多東西,比較難直接升級。so.. 只能現在這個基礎上解決問題。
1.先看mat分析出來的 強引用路徑

Eclipse Memory Analyzer MemoryAnalyzer, 前天 at 22.39.32.png
最下面是被StringRequest引用著,他引用著requestNet:網路請求的工具類,又引用著另一箇中間層封裝的工具類,最後就是不能被回收的記憶體大頭。
- 肯定是把不能回收的活動的引用傳入了StringRequest裡面,有了強引用關係導致的。檢查程式碼,發現是網路請求的回撥,專案都是實現一個回撥的介面,請求網路把自己當listener,但是為什麼不能被回收呢。即使網路請求完成了,也不行。
上網查了查,也有遇到這個問題的,有說把傳入的引用宣告為軟引用或弱引用的。
java引用從強到弱分別是:強軟弱虛 強引用:就是我們宣告最多的引用,直接宣告 軟引用:不靠譜的引用,當記憶體不足時就回收(原來一直以為是oom之前回收,其實 不是不是是不是 ) 弱引用:GC看到就是回收,更不靠譜的引用 虛引用:形同虛設,一般用在GC內部 當然能夠回收的前提是沒有任何強引用拉著它。
好了,既然有強引用引著它,那就把傳入volley的activity引用宣告為軟引用或弱引用就行了唄,還是軟引用吧,至少不會像弱引用那麼不靠譜。好的開始做,嗯,果然被回收掉了。
但是有一個問題,時不時就會沒有資料返回,因為網路的回撥被回收了,一隻轉圈,體驗極差。我一直認為軟引用是在OOM發生前會回收的,其實不是。它是在GC回收完成後,可用記憶體如果小於10M(預設是這個值,app可用記憶體越多,這個值就越大)時就會回收(沒有其他強引用拉著)。所以說非常非常容易被回收的。很不靠譜。
*** 所以宣告成軟引用是不行的。***
為什麼回收不掉呢,想了想可能和執行緒的方法棧有關,volley內部有一個執行緒池,這個執行緒執行完後,沒有停止或回收裡面的執行緒,導致方法棧(GCRoot)一隻拉著不能回收。多請求幾次網路,前幾次的就能被回收了,確實有這個現象發生。看看volley有沒有停止的方法吧,果然有。
這個一加就可以了。具體內部的細節還會再研究, 有知道的大神可以分享一下,謝謝啦。
public void finish() { try { Volley.getReqQueue().stop(); }catch (Exception e){ e.printStackTrace(); } }